typescript-virtual-container 1.4.4 → 1.4.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 (892) hide show
  1. package/builds/self-standalone.js +321 -272
  2. package/builds/self-standalone.js.map +4 -4
  3. package/builds/standalone-wo-sftp.js +261 -212
  4. package/builds/standalone-wo-sftp.js.map +4 -4
  5. package/builds/standalone.js +265 -216
  6. package/builds/standalone.js.map +4 -4
  7. package/builds/web-full-api.min.js +5 -5
  8. package/builds/web-full-api.min.js.map +3 -3
  9. package/builds/web.min.js +5 -5
  10. package/builds/web.min.js.map +3 -3
  11. package/bun.lock +97 -0
  12. package/dist/Honeypot/index.d.ts.map +1 -0
  13. package/dist/Honeypot/index.js +299 -0
  14. package/dist/Honeypot/index.js.map +1 -0
  15. package/dist/SSHClient/index.d.ts.map +1 -0
  16. package/dist/SSHClient/index.js +238 -0
  17. package/dist/SSHClient/index.js.map +1 -0
  18. package/dist/SSHMimic/exec.d.ts.map +1 -0
  19. package/dist/SSHMimic/exec.js +28 -0
  20. package/dist/SSHMimic/exec.js.map +1 -0
  21. package/dist/SSHMimic/executor.d.ts.map +1 -0
  22. package/dist/SSHMimic/executor.js +161 -0
  23. package/dist/SSHMimic/executor.js.map +1 -0
  24. package/dist/SSHMimic/hostKey.d.ts.map +1 -0
  25. package/dist/SSHMimic/hostKey.js +18 -0
  26. package/dist/SSHMimic/hostKey.js.map +1 -0
  27. package/dist/SSHMimic/index.d.ts.map +1 -0
  28. package/dist/SSHMimic/index.js +250 -0
  29. package/dist/SSHMimic/index.js.map +1 -0
  30. package/dist/SSHMimic/loginBanner.d.ts.map +1 -0
  31. package/dist/SSHMimic/loginBanner.js +23 -0
  32. package/dist/SSHMimic/loginBanner.js.map +1 -0
  33. package/dist/SSHMimic/loginFormat.d.ts.map +1 -0
  34. package/dist/SSHMimic/loginFormat.js +11 -0
  35. package/dist/SSHMimic/loginFormat.js.map +1 -0
  36. package/dist/SSHMimic/prompt.d.ts.map +1 -0
  37. package/dist/SSHMimic/prompt.js +10 -0
  38. package/dist/SSHMimic/prompt.js.map +1 -0
  39. package/dist/SSHMimic/sftp.d.ts.map +1 -0
  40. package/dist/SSHMimic/sftp.js +620 -0
  41. package/dist/SSHMimic/sftp.js.map +1 -0
  42. package/dist/VirtualFileSystem/binaryPack.d.ts.map +1 -0
  43. package/dist/VirtualFileSystem/binaryPack.js +217 -0
  44. package/dist/VirtualFileSystem/binaryPack.js.map +1 -0
  45. package/dist/VirtualFileSystem/index.d.ts.map +1 -0
  46. package/dist/VirtualFileSystem/index.js +690 -0
  47. package/dist/VirtualFileSystem/index.js.map +1 -0
  48. package/dist/VirtualFileSystem/internalTypes.d.ts.map +1 -0
  49. package/dist/VirtualFileSystem/internalTypes.js +1 -0
  50. package/dist/VirtualFileSystem/internalTypes.js.map +1 -0
  51. package/dist/VirtualFileSystem/path.d.ts.map +1 -0
  52. package/dist/VirtualFileSystem/path.js +50 -0
  53. package/dist/VirtualFileSystem/path.js.map +1 -0
  54. package/dist/VirtualPackageManager/index.d.ts.map +1 -0
  55. package/dist/VirtualPackageManager/index.js +854 -0
  56. package/dist/VirtualPackageManager/index.js.map +1 -0
  57. package/dist/VirtualShell/index.d.ts.map +1 -0
  58. package/dist/VirtualShell/index.js +285 -0
  59. package/dist/VirtualShell/index.js.map +1 -0
  60. package/dist/VirtualShell/shell.d.ts.map +1 -0
  61. package/dist/VirtualShell/shell.js +503 -0
  62. package/dist/VirtualShell/shell.js.map +1 -0
  63. package/dist/VirtualShell/shellParser.d.ts.map +1 -0
  64. package/dist/VirtualShell/shellParser.js +266 -0
  65. package/dist/VirtualShell/shellParser.js.map +1 -0
  66. package/dist/VirtualUserManager/index.d.ts.map +1 -0
  67. package/dist/VirtualUserManager/index.js +608 -0
  68. package/dist/VirtualUserManager/index.js.map +1 -0
  69. package/dist/commands/adduser.d.ts.map +1 -0
  70. package/dist/commands/adduser.js +90 -0
  71. package/dist/commands/adduser.js.map +1 -0
  72. package/dist/commands/alias.d.ts.map +1 -0
  73. package/dist/commands/alias.js +69 -0
  74. package/dist/commands/alias.js.map +1 -0
  75. package/dist/commands/apt.d.ts.map +1 -0
  76. package/dist/commands/apt.js +211 -0
  77. package/dist/commands/apt.js.map +1 -0
  78. package/dist/commands/awk.d.ts.map +1 -0
  79. package/dist/commands/awk.js +170 -0
  80. package/dist/commands/awk.js.map +1 -0
  81. package/dist/commands/base64.d.ts.map +1 -0
  82. package/dist/commands/base64.js +29 -0
  83. package/dist/commands/base64.js.map +1 -0
  84. package/dist/commands/cat.d.ts.map +1 -0
  85. package/dist/commands/cat.js +45 -0
  86. package/dist/commands/cat.js.map +1 -0
  87. package/dist/commands/cd.d.ts.map +1 -0
  88. package/dist/commands/cd.js +22 -0
  89. package/dist/commands/cd.js.map +1 -0
  90. package/dist/commands/chmod.d.ts.map +1 -0
  91. package/dist/commands/chmod.js +88 -0
  92. package/dist/commands/chmod.js.map +1 -0
  93. package/dist/commands/clear.d.ts.map +1 -0
  94. package/dist/commands/clear.js +14 -0
  95. package/dist/commands/clear.js.map +1 -0
  96. package/dist/commands/command-helpers.d.ts.map +1 -0
  97. package/dist/commands/command-helpers.js +222 -0
  98. package/dist/commands/command-helpers.js.map +1 -0
  99. package/dist/commands/cp.d.ts.map +1 -0
  100. package/dist/commands/cp.js +76 -0
  101. package/dist/commands/cp.js.map +1 -0
  102. package/dist/commands/curl.d.ts.map +1 -0
  103. package/dist/commands/curl.js +128 -0
  104. package/dist/commands/curl.js.map +1 -0
  105. package/dist/commands/cut.d.ts.map +1 -0
  106. package/dist/commands/cut.js +35 -0
  107. package/dist/commands/cut.js.map +1 -0
  108. package/dist/commands/date.d.ts.map +1 -0
  109. package/dist/commands/date.js +29 -0
  110. package/dist/commands/date.js.map +1 -0
  111. package/dist/commands/declare.d.ts.map +1 -0
  112. package/dist/commands/declare.js +45 -0
  113. package/dist/commands/declare.js.map +1 -0
  114. package/dist/commands/deluser.d.ts.map +1 -0
  115. package/dist/commands/deluser.js +84 -0
  116. package/dist/commands/deluser.js.map +1 -0
  117. package/dist/commands/df.d.ts.map +1 -0
  118. package/dist/commands/df.js +22 -0
  119. package/dist/commands/df.js.map +1 -0
  120. package/dist/commands/diff.d.ts.map +1 -0
  121. package/dist/commands/diff.js +46 -0
  122. package/dist/commands/diff.js.map +1 -0
  123. package/dist/commands/dpkg.d.ts.map +1 -0
  124. package/dist/commands/dpkg.js +162 -0
  125. package/dist/commands/dpkg.js.map +1 -0
  126. package/dist/commands/du.d.ts.map +1 -0
  127. package/dist/commands/du.js +51 -0
  128. package/dist/commands/du.js.map +1 -0
  129. package/dist/commands/echo.d.ts.map +1 -0
  130. package/dist/commands/echo.js +46 -0
  131. package/dist/commands/echo.js.map +1 -0
  132. package/dist/commands/env.d.ts.map +1 -0
  133. package/dist/commands/env.js +21 -0
  134. package/dist/commands/env.js.map +1 -0
  135. package/dist/commands/exit.d.ts.map +1 -0
  136. package/dist/commands/exit.js +17 -0
  137. package/dist/commands/exit.js.map +1 -0
  138. package/dist/commands/export.d.ts.map +1 -0
  139. package/dist/commands/export.js +34 -0
  140. package/dist/commands/export.js.map +1 -0
  141. package/dist/commands/find.d.ts.map +1 -0
  142. package/dist/commands/find.js +56 -0
  143. package/dist/commands/find.js.map +1 -0
  144. package/dist/commands/free.d.ts.map +1 -0
  145. package/dist/commands/free.js +44 -0
  146. package/dist/commands/free.js.map +1 -0
  147. package/dist/commands/grep.d.ts.map +1 -0
  148. package/dist/commands/grep.js +121 -0
  149. package/dist/commands/grep.js.map +1 -0
  150. package/dist/commands/groups.d.ts.map +1 -0
  151. package/dist/commands/groups.js +18 -0
  152. package/dist/commands/groups.js.map +1 -0
  153. package/dist/commands/gzip.d.ts.map +1 -0
  154. package/dist/commands/gzip.js +83 -0
  155. package/dist/commands/gzip.js.map +1 -0
  156. package/dist/commands/head.d.ts.map +1 -0
  157. package/dist/commands/head.js +47 -0
  158. package/dist/commands/head.js.map +1 -0
  159. package/dist/commands/help.d.ts.map +1 -0
  160. package/dist/commands/help.js +124 -0
  161. package/dist/commands/help.js.map +1 -0
  162. package/dist/commands/helpers.d.ts.map +1 -0
  163. package/dist/commands/helpers.js +167 -0
  164. package/dist/commands/helpers.js.map +1 -0
  165. package/dist/commands/history.d.ts.map +1 -0
  166. package/dist/commands/history.js +27 -0
  167. package/dist/commands/history.js.map +1 -0
  168. package/dist/commands/hostname.d.ts.map +1 -0
  169. package/dist/commands/hostname.js +13 -0
  170. package/dist/commands/hostname.js.map +1 -0
  171. package/dist/commands/htop.d.ts.map +1 -0
  172. package/dist/commands/htop.js +18 -0
  173. package/dist/commands/htop.js.map +1 -0
  174. package/dist/commands/id.d.ts.map +1 -0
  175. package/dist/commands/id.js +18 -0
  176. package/dist/commands/id.js.map +1 -0
  177. package/dist/commands/index.d.ts.map +1 -0
  178. package/dist/commands/index.js +3 -0
  179. package/dist/commands/index.js.map +1 -0
  180. package/dist/commands/kill.d.ts.map +1 -0
  181. package/dist/commands/kill.js +19 -0
  182. package/dist/commands/kill.js.map +1 -0
  183. package/dist/commands/ln.d.ts.map +1 -0
  184. package/dist/commands/ln.js +67 -0
  185. package/dist/commands/ln.js.map +1 -0
  186. package/dist/commands/ls.d.ts.map +1 -0
  187. package/dist/commands/ls.js +201 -0
  188. package/dist/commands/ls.js.map +1 -0
  189. package/dist/commands/lsb-release.d.ts.map +1 -0
  190. package/dist/commands/lsb-release.js +62 -0
  191. package/dist/commands/lsb-release.js.map +1 -0
  192. package/dist/commands/man.d.ts.map +1 -0
  193. package/dist/commands/man.js +50 -0
  194. package/dist/commands/man.js.map +1 -0
  195. package/dist/commands/mkdir.d.ts.map +1 -0
  196. package/dist/commands/mkdir.js +29 -0
  197. package/dist/commands/mkdir.js.map +1 -0
  198. package/dist/commands/mv.d.ts.map +1 -0
  199. package/dist/commands/mv.js +43 -0
  200. package/dist/commands/mv.js.map +1 -0
  201. package/dist/commands/nano.d.ts.map +1 -0
  202. package/dist/commands/nano.js +35 -0
  203. package/dist/commands/nano.js.map +1 -0
  204. package/dist/commands/neofetch.d.ts.map +1 -0
  205. package/dist/commands/neofetch.js +49 -0
  206. package/dist/commands/neofetch.js.map +1 -0
  207. package/dist/commands/node.d.ts.map +1 -0
  208. package/dist/commands/node.js +317 -0
  209. package/dist/commands/node.js.map +1 -0
  210. package/dist/commands/npm.d.ts.map +1 -0
  211. package/dist/commands/npm.js +110 -0
  212. package/dist/commands/npm.js.map +1 -0
  213. package/dist/commands/passwd.d.ts.map +1 -0
  214. package/dist/commands/passwd.js +45 -0
  215. package/dist/commands/passwd.js.map +1 -0
  216. package/dist/commands/ping.d.ts.map +1 -0
  217. package/dist/commands/ping.js +29 -0
  218. package/dist/commands/ping.js.map +1 -0
  219. package/dist/commands/printf.d.ts.map +1 -0
  220. package/dist/commands/printf.js +145 -0
  221. package/dist/commands/printf.js.map +1 -0
  222. package/dist/commands/ps.d.ts.map +1 -0
  223. package/dist/commands/ps.js +47 -0
  224. package/dist/commands/ps.js.map +1 -0
  225. package/dist/commands/pwd.d.ts.map +1 -0
  226. package/dist/commands/pwd.js +8 -0
  227. package/dist/commands/pwd.js.map +1 -0
  228. package/dist/commands/python.d.ts.map +1 -0
  229. package/dist/commands/python.js +2059 -0
  230. package/dist/commands/python.js.map +1 -0
  231. package/dist/commands/read.d.ts.map +1 -0
  232. package/dist/commands/read.js +40 -0
  233. package/dist/commands/read.js.map +1 -0
  234. package/dist/commands/registry.d.ts.map +1 -0
  235. package/dist/commands/registry.js +235 -0
  236. package/dist/commands/registry.js.map +1 -0
  237. package/dist/commands/rm.d.ts.map +1 -0
  238. package/dist/commands/rm.js +37 -0
  239. package/dist/commands/rm.js.map +1 -0
  240. package/dist/commands/runtime.d.ts.map +1 -0
  241. package/dist/commands/runtime.js +286 -0
  242. package/dist/commands/runtime.js.map +1 -0
  243. package/dist/commands/sed.d.ts.map +1 -0
  244. package/dist/commands/sed.js +61 -0
  245. package/dist/commands/sed.js.map +1 -0
  246. package/dist/commands/seq.d.ts.map +1 -0
  247. package/dist/commands/seq.js +51 -0
  248. package/dist/commands/seq.js.map +1 -0
  249. package/dist/commands/set.d.ts.map +1 -0
  250. package/dist/commands/set.js +27 -0
  251. package/dist/commands/set.js.map +1 -0
  252. package/dist/commands/sh.d.ts.map +1 -0
  253. package/dist/commands/sh.js +432 -0
  254. package/dist/commands/sh.js.map +1 -0
  255. package/dist/commands/shift.d.ts.map +1 -0
  256. package/dist/commands/shift.js +63 -0
  257. package/dist/commands/shift.js.map +1 -0
  258. package/dist/commands/sleep.d.ts.map +1 -0
  259. package/dist/commands/sleep.js +19 -0
  260. package/dist/commands/sleep.js.map +1 -0
  261. package/dist/commands/sort.d.ts.map +1 -0
  262. package/dist/commands/sort.js +45 -0
  263. package/dist/commands/sort.js.map +1 -0
  264. package/dist/commands/source.d.ts.map +1 -0
  265. package/dist/commands/source.js +40 -0
  266. package/dist/commands/source.js.map +1 -0
  267. package/dist/commands/stat.d.ts.map +1 -0
  268. package/dist/commands/stat.js +57 -0
  269. package/dist/commands/stat.js.map +1 -0
  270. package/dist/commands/su.d.ts.map +1 -0
  271. package/dist/commands/su.js +58 -0
  272. package/dist/commands/su.js.map +1 -0
  273. package/dist/commands/sudo.d.ts.map +1 -0
  274. package/dist/commands/sudo.js +55 -0
  275. package/dist/commands/sudo.js.map +1 -0
  276. package/dist/commands/tail.d.ts.map +1 -0
  277. package/dist/commands/tail.js +48 -0
  278. package/dist/commands/tail.js.map +1 -0
  279. package/dist/commands/tar.d.ts.map +1 -0
  280. package/dist/commands/tar.js +103 -0
  281. package/dist/commands/tar.js.map +1 -0
  282. package/dist/commands/tee.d.ts.map +1 -0
  283. package/dist/commands/tee.js +37 -0
  284. package/dist/commands/tee.js.map +1 -0
  285. package/dist/commands/test.d.ts.map +1 -0
  286. package/dist/commands/test.js +115 -0
  287. package/dist/commands/test.js.map +1 -0
  288. package/dist/commands/touch.d.ts.map +1 -0
  289. package/dist/commands/touch.js +26 -0
  290. package/dist/commands/touch.js.map +1 -0
  291. package/dist/commands/tr.d.ts.map +1 -0
  292. package/dist/commands/tr.js +62 -0
  293. package/dist/commands/tr.js.map +1 -0
  294. package/dist/commands/tree.d.ts.map +1 -0
  295. package/dist/commands/tree.js +19 -0
  296. package/dist/commands/tree.js.map +1 -0
  297. package/dist/commands/true.d.ts.map +1 -0
  298. package/dist/commands/true.js +25 -0
  299. package/dist/commands/true.js.map +1 -0
  300. package/dist/commands/type.d.ts.map +1 -0
  301. package/dist/commands/type.js +40 -0
  302. package/dist/commands/type.js.map +1 -0
  303. package/dist/commands/uname.d.ts.map +1 -0
  304. package/dist/commands/uname.js +30 -0
  305. package/dist/commands/uname.js.map +1 -0
  306. package/dist/commands/uniq.d.ts.map +1 -0
  307. package/dist/commands/uniq.js +39 -0
  308. package/dist/commands/uniq.js.map +1 -0
  309. package/dist/commands/unset.d.ts.map +1 -0
  310. package/dist/commands/unset.js +17 -0
  311. package/dist/commands/unset.js.map +1 -0
  312. package/dist/commands/uptime.d.ts.map +1 -0
  313. package/dist/commands/uptime.js +49 -0
  314. package/dist/commands/uptime.js.map +1 -0
  315. package/dist/commands/wc.d.ts.map +1 -0
  316. package/dist/commands/wc.js +56 -0
  317. package/dist/commands/wc.js.map +1 -0
  318. package/dist/commands/wget.d.ts.map +1 -0
  319. package/dist/commands/wget.js +127 -0
  320. package/dist/commands/wget.js.map +1 -0
  321. package/dist/commands/which.d.ts.map +1 -0
  322. package/dist/commands/which.js +33 -0
  323. package/dist/commands/which.js.map +1 -0
  324. package/dist/commands/who.d.ts.map +1 -0
  325. package/dist/commands/who.js +23 -0
  326. package/dist/commands/who.js.map +1 -0
  327. package/dist/commands/whoami.d.ts.map +1 -0
  328. package/dist/commands/whoami.js +13 -0
  329. package/dist/commands/whoami.js.map +1 -0
  330. package/dist/commands/xargs.d.ts.map +1 -0
  331. package/dist/commands/xargs.js +22 -0
  332. package/dist/commands/xargs.js.map +1 -0
  333. package/dist/index.d.ts.map +1 -0
  334. package/dist/index.js +10 -0
  335. package/dist/index.js.map +1 -0
  336. package/dist/modules/linuxRootfs.d.ts.map +1 -0
  337. package/dist/modules/linuxRootfs.js +620 -0
  338. package/dist/modules/linuxRootfs.js.map +1 -0
  339. package/dist/modules/neofetch.d.ts.map +1 -0
  340. package/dist/modules/neofetch.js +285 -0
  341. package/dist/modules/neofetch.js.map +1 -0
  342. package/dist/modules/shellInteractive.d.ts.map +1 -0
  343. package/dist/modules/shellInteractive.js +27 -0
  344. package/dist/modules/shellInteractive.js.map +1 -0
  345. package/dist/modules/shellRuntime.d.ts.map +1 -0
  346. package/dist/modules/shellRuntime.js +53 -0
  347. package/dist/modules/shellRuntime.js.map +1 -0
  348. package/dist/self-standalone.d.ts.map +1 -0
  349. package/dist/self-standalone.js +419 -0
  350. package/dist/self-standalone.js.map +1 -0
  351. package/dist/standalone-wo-sftp.d.ts.map +1 -0
  352. package/dist/standalone-wo-sftp.js +31 -0
  353. package/dist/standalone-wo-sftp.js.map +1 -0
  354. package/dist/standalone.d.ts.map +1 -0
  355. package/dist/standalone.js +36 -0
  356. package/dist/standalone.js.map +1 -0
  357. package/dist/types/commands.d.ts.map +1 -0
  358. package/dist/types/commands.js +1 -0
  359. package/dist/types/commands.js.map +1 -0
  360. package/dist/types/pipeline.d.ts.map +1 -0
  361. package/dist/types/pipeline.js +1 -0
  362. package/dist/types/pipeline.js.map +1 -0
  363. package/dist/types/streams.d.ts.map +1 -0
  364. package/dist/types/streams.js +1 -0
  365. package/dist/types/streams.js.map +1 -0
  366. package/dist/types/vfs.d.ts.map +1 -0
  367. package/dist/types/vfs.js +1 -0
  368. package/dist/types/vfs.js.map +1 -0
  369. package/dist/utils/expand.d.ts.map +1 -0
  370. package/dist/utils/expand.js +477 -0
  371. package/dist/utils/expand.js.map +1 -0
  372. package/dist/utils/perfLogger.d.ts.map +1 -0
  373. package/dist/utils/perfLogger.js +50 -0
  374. package/dist/utils/perfLogger.js.map +1 -0
  375. package/dist/utils/tokenize.d.ts.map +1 -0
  376. package/dist/utils/tokenize.js +115 -0
  377. package/dist/utils/tokenize.js.map +1 -0
  378. package/dist/utils/vfsDiff.d.ts.map +1 -0
  379. package/dist/utils/vfsDiff.js +178 -0
  380. package/dist/utils/vfsDiff.js.map +1 -0
  381. package/dist/web-api.d.ts.map +1 -0
  382. package/dist/web-api.js +47 -0
  383. package/dist/web-api.js.map +1 -0
  384. package/dist/web-full.d.ts.map +1 -0
  385. package/dist/web-full.js +9 -0
  386. package/dist/web-full.js.map +1 -0
  387. package/dist/web.d.ts.map +1 -0
  388. package/dist/web.js +774 -0
  389. package/dist/web.js.map +1 -0
  390. package/docs/.nojekyll +1 -0
  391. package/docs/assets/hierarchy.js +1 -0
  392. package/docs/assets/highlight.css +162 -0
  393. package/docs/assets/icons.js +18 -0
  394. package/docs/assets/icons.svg +1 -0
  395. package/docs/assets/main.js +60 -0
  396. package/docs/assets/navigation.js +1 -0
  397. package/docs/assets/search.js +1 -0
  398. package/docs/assets/style.css +1633 -0
  399. package/docs/classes/HoneyPot.html +31 -0
  400. package/docs/classes/SshClient.html +66 -0
  401. package/docs/classes/VirtualFileSystem.html +262 -0
  402. package/docs/classes/VirtualPackageManager.html +63 -0
  403. package/docs/classes/VirtualSftpServer.html +169 -0
  404. package/docs/classes/VirtualShell.html +265 -0
  405. package/docs/classes/VirtualSshServer.html +177 -0
  406. package/docs/classes/VirtualUserManager.html +276 -0
  407. package/docs/docs/.nojekyll +1 -0
  408. package/docs/docs/assets/hierarchy.js +1 -0
  409. package/docs/docs/assets/highlight.css +162 -0
  410. package/docs/docs/assets/icons.js +18 -0
  411. package/docs/docs/assets/icons.svg +1 -0
  412. package/docs/docs/assets/main.js +60 -0
  413. package/docs/docs/assets/navigation.js +1 -0
  414. package/docs/docs/assets/search.js +1 -0
  415. package/docs/docs/assets/style.css +1633 -0
  416. package/docs/docs/hierarchy.html +1 -0
  417. package/docs/docs/index.html +1842 -0
  418. package/docs/docs/media/LICENSE +21 -0
  419. package/docs/docs/modules.html +1 -0
  420. package/docs/functions/assertDiff.html +6 -0
  421. package/docs/functions/diffSnapshots.html +7 -0
  422. package/docs/functions/formatDiff.html +6 -0
  423. package/docs/functions/getArg.html +13 -0
  424. package/docs/functions/getFlag.html +15 -0
  425. package/docs/functions/ifFlag.html +11 -0
  426. package/docs/hierarchy.html +1 -0
  427. package/docs/index.html +1842 -0
  428. package/docs/interfaces/AuditLogEntry.html +6 -0
  429. package/docs/interfaces/CommandContext.html +22 -0
  430. package/docs/interfaces/CommandResult.html +26 -0
  431. package/docs/interfaces/ExecStream.html +11 -0
  432. package/docs/interfaces/HoneyPotStats.html +14 -0
  433. package/docs/interfaces/InstalledPackage.html +20 -0
  434. package/docs/interfaces/NanoEditorSession.html +8 -0
  435. package/docs/interfaces/PackageDefinition.html +30 -0
  436. package/docs/interfaces/PackageFile.html +8 -0
  437. package/docs/interfaces/RemoveOptions.html +4 -0
  438. package/docs/interfaces/ShellEnv.html +6 -0
  439. package/docs/interfaces/ShellModule.html +14 -0
  440. package/docs/interfaces/ShellProperties.html +14 -0
  441. package/docs/interfaces/ShellStream.html +11 -0
  442. package/docs/interfaces/SudoChallenge.html +24 -0
  443. package/docs/interfaces/VfsBaseNode.html +12 -0
  444. package/docs/interfaces/VfsDiff.html +10 -0
  445. package/docs/interfaces/VfsDiffEntry.html +6 -0
  446. package/docs/interfaces/VfsDiffModified.html +10 -0
  447. package/docs/interfaces/VfsDirectoryNode.html +15 -0
  448. package/docs/interfaces/VfsFileNode.html +17 -0
  449. package/docs/interfaces/VfsOptions.html +12 -0
  450. package/docs/interfaces/VfsSnapshot.html +3 -0
  451. package/docs/interfaces/VfsSnapshotBaseNode.html +8 -0
  452. package/docs/interfaces/VfsSnapshotDirectoryNode.html +10 -0
  453. package/docs/interfaces/VfsSnapshotFileNode.html +12 -0
  454. package/docs/interfaces/WriteFileOptions.html +6 -0
  455. package/docs/media/LICENSE +21 -0
  456. package/docs/modules.html +1 -0
  457. package/docs/types/CommandMode.html +2 -0
  458. package/docs/types/CommandOutcome.html +2 -0
  459. package/docs/types/VfsNodeStats.html +2 -0
  460. package/docs/types/VfsNodeType.html +2 -0
  461. package/docs/types/VfsPersistenceMode.html +5 -0
  462. package/docs/types/VfsSnapshotNode.html +2 -0
  463. package/examples/web.min.js +5 -5
  464. package/package.json +4 -2
  465. package/tsconfig.json +7 -2
  466. package/typedoc.json +8 -0
  467. package/src/Honeypot/index.d.ts.map +0 -1
  468. package/src/Honeypot/index.js +0 -298
  469. package/src/SSHClient/index.d.ts.map +0 -1
  470. package/src/SSHClient/index.js +0 -237
  471. package/src/SSHMimic/exec.d.ts.map +0 -1
  472. package/src/SSHMimic/exec.js +0 -27
  473. package/src/SSHMimic/executor.d.ts.map +0 -1
  474. package/src/SSHMimic/executor.js +0 -160
  475. package/src/SSHMimic/hostKey.d.ts.map +0 -1
  476. package/src/SSHMimic/hostKey.js +0 -17
  477. package/src/SSHMimic/index.d.ts.map +0 -1
  478. package/src/SSHMimic/index.js +0 -249
  479. package/src/SSHMimic/loginBanner.d.ts.map +0 -1
  480. package/src/SSHMimic/loginBanner.js +0 -22
  481. package/src/SSHMimic/loginFormat.d.ts.map +0 -1
  482. package/src/SSHMimic/loginFormat.js +0 -10
  483. package/src/SSHMimic/prompt.d.ts.map +0 -1
  484. package/src/SSHMimic/prompt.js +0 -9
  485. package/src/SSHMimic/sftp.d.ts.map +0 -1
  486. package/src/SSHMimic/sftp.js +0 -619
  487. package/src/VirtualFileSystem/binaryPack.d.ts.map +0 -1
  488. package/src/VirtualFileSystem/binaryPack.js +0 -216
  489. package/src/VirtualFileSystem/index.d.ts.map +0 -1
  490. package/src/VirtualFileSystem/index.js +0 -689
  491. package/src/VirtualFileSystem/internalTypes.d.ts.map +0 -1
  492. package/src/VirtualFileSystem/internalTypes.js +0 -0
  493. package/src/VirtualFileSystem/path.d.ts.map +0 -1
  494. package/src/VirtualFileSystem/path.js +0 -49
  495. package/src/VirtualPackageManager/index.d.ts.map +0 -1
  496. package/src/VirtualPackageManager/index.js +0 -853
  497. package/src/VirtualShell/index.d.ts.map +0 -1
  498. package/src/VirtualShell/index.js +0 -284
  499. package/src/VirtualShell/shell.d.ts.map +0 -1
  500. package/src/VirtualShell/shell.js +0 -502
  501. package/src/VirtualShell/shellParser.d.ts.map +0 -1
  502. package/src/VirtualShell/shellParser.js +0 -265
  503. package/src/VirtualUserManager/index.d.ts.map +0 -1
  504. package/src/VirtualUserManager/index.js +0 -607
  505. package/src/commands/adduser.d.ts.map +0 -1
  506. package/src/commands/adduser.js +0 -89
  507. package/src/commands/alias.d.ts.map +0 -1
  508. package/src/commands/alias.js +0 -68
  509. package/src/commands/apt.d.ts.map +0 -1
  510. package/src/commands/apt.js +0 -210
  511. package/src/commands/awk.d.ts.map +0 -1
  512. package/src/commands/awk.js +0 -169
  513. package/src/commands/base64.d.ts.map +0 -1
  514. package/src/commands/base64.js +0 -28
  515. package/src/commands/cat.d.ts.map +0 -1
  516. package/src/commands/cat.js +0 -44
  517. package/src/commands/cd.d.ts.map +0 -1
  518. package/src/commands/cd.js +0 -21
  519. package/src/commands/chmod.d.ts.map +0 -1
  520. package/src/commands/chmod.js +0 -87
  521. package/src/commands/clear.d.ts.map +0 -1
  522. package/src/commands/clear.js +0 -13
  523. package/src/commands/command-helpers.d.ts.map +0 -1
  524. package/src/commands/command-helpers.js +0 -221
  525. package/src/commands/cp.d.ts.map +0 -1
  526. package/src/commands/cp.js +0 -75
  527. package/src/commands/curl.d.ts.map +0 -1
  528. package/src/commands/curl.js +0 -127
  529. package/src/commands/cut.d.ts.map +0 -1
  530. package/src/commands/cut.js +0 -34
  531. package/src/commands/date.d.ts.map +0 -1
  532. package/src/commands/date.js +0 -28
  533. package/src/commands/declare.d.ts.map +0 -1
  534. package/src/commands/declare.js +0 -44
  535. package/src/commands/deluser.d.ts.map +0 -1
  536. package/src/commands/deluser.js +0 -83
  537. package/src/commands/df.d.ts.map +0 -1
  538. package/src/commands/df.js +0 -21
  539. package/src/commands/diff.d.ts.map +0 -1
  540. package/src/commands/diff.js +0 -45
  541. package/src/commands/dpkg.d.ts.map +0 -1
  542. package/src/commands/dpkg.js +0 -161
  543. package/src/commands/du.d.ts.map +0 -1
  544. package/src/commands/du.js +0 -50
  545. package/src/commands/echo.d.ts.map +0 -1
  546. package/src/commands/echo.js +0 -45
  547. package/src/commands/env.d.ts.map +0 -1
  548. package/src/commands/env.js +0 -20
  549. package/src/commands/exit.d.ts.map +0 -1
  550. package/src/commands/exit.js +0 -16
  551. package/src/commands/export.d.ts.map +0 -1
  552. package/src/commands/export.js +0 -33
  553. package/src/commands/find.d.ts.map +0 -1
  554. package/src/commands/find.js +0 -55
  555. package/src/commands/free.d.ts.map +0 -1
  556. package/src/commands/free.js +0 -43
  557. package/src/commands/grep.d.ts.map +0 -1
  558. package/src/commands/grep.js +0 -120
  559. package/src/commands/groups.d.ts.map +0 -1
  560. package/src/commands/groups.js +0 -17
  561. package/src/commands/gzip.d.ts.map +0 -1
  562. package/src/commands/gzip.js +0 -82
  563. package/src/commands/head.d.ts.map +0 -1
  564. package/src/commands/head.js +0 -46
  565. package/src/commands/help.d.ts.map +0 -1
  566. package/src/commands/help.js +0 -123
  567. package/src/commands/helpers.d.ts.map +0 -1
  568. package/src/commands/helpers.js +0 -166
  569. package/src/commands/history.d.ts.map +0 -1
  570. package/src/commands/history.js +0 -26
  571. package/src/commands/hostname.d.ts.map +0 -1
  572. package/src/commands/hostname.js +0 -12
  573. package/src/commands/htop.d.ts.map +0 -1
  574. package/src/commands/htop.js +0 -17
  575. package/src/commands/id.d.ts.map +0 -1
  576. package/src/commands/id.js +0 -17
  577. package/src/commands/index.d.ts.map +0 -1
  578. package/src/commands/index.js +0 -2
  579. package/src/commands/kill.d.ts.map +0 -1
  580. package/src/commands/kill.js +0 -18
  581. package/src/commands/ln.d.ts.map +0 -1
  582. package/src/commands/ln.js +0 -66
  583. package/src/commands/ls.d.ts.map +0 -1
  584. package/src/commands/ls.js +0 -200
  585. package/src/commands/lsb-release.d.ts.map +0 -1
  586. package/src/commands/lsb-release.js +0 -61
  587. package/src/commands/man.d.ts.map +0 -1
  588. package/src/commands/man.js +0 -49
  589. package/src/commands/mkdir.d.ts.map +0 -1
  590. package/src/commands/mkdir.js +0 -28
  591. package/src/commands/mv.d.ts.map +0 -1
  592. package/src/commands/mv.js +0 -42
  593. package/src/commands/nano.d.ts.map +0 -1
  594. package/src/commands/nano.js +0 -34
  595. package/src/commands/neofetch.d.ts.map +0 -1
  596. package/src/commands/neofetch.js +0 -48
  597. package/src/commands/node.d.ts.map +0 -1
  598. package/src/commands/node.js +0 -316
  599. package/src/commands/npm.d.ts.map +0 -1
  600. package/src/commands/npm.js +0 -109
  601. package/src/commands/passwd.d.ts.map +0 -1
  602. package/src/commands/passwd.js +0 -44
  603. package/src/commands/ping.d.ts.map +0 -1
  604. package/src/commands/ping.js +0 -28
  605. package/src/commands/printf.d.ts.map +0 -1
  606. package/src/commands/printf.js +0 -144
  607. package/src/commands/ps.d.ts.map +0 -1
  608. package/src/commands/ps.js +0 -46
  609. package/src/commands/pwd.d.ts.map +0 -1
  610. package/src/commands/pwd.js +0 -7
  611. package/src/commands/python.d.ts.map +0 -1
  612. package/src/commands/python.js +0 -2058
  613. package/src/commands/read.d.ts.map +0 -1
  614. package/src/commands/read.js +0 -39
  615. package/src/commands/registry.d.ts.map +0 -1
  616. package/src/commands/registry.js +0 -234
  617. package/src/commands/rm.d.ts.map +0 -1
  618. package/src/commands/rm.js +0 -36
  619. package/src/commands/runtime.d.ts.map +0 -1
  620. package/src/commands/runtime.js +0 -285
  621. package/src/commands/sed.d.ts.map +0 -1
  622. package/src/commands/sed.js +0 -60
  623. package/src/commands/seq.d.ts.map +0 -1
  624. package/src/commands/seq.js +0 -50
  625. package/src/commands/set.d.ts.map +0 -1
  626. package/src/commands/set.js +0 -26
  627. package/src/commands/sh.d.ts.map +0 -1
  628. package/src/commands/sh.js +0 -431
  629. package/src/commands/shift.d.ts.map +0 -1
  630. package/src/commands/shift.js +0 -62
  631. package/src/commands/sleep.d.ts.map +0 -1
  632. package/src/commands/sleep.js +0 -18
  633. package/src/commands/sort.d.ts.map +0 -1
  634. package/src/commands/sort.js +0 -44
  635. package/src/commands/source.d.ts.map +0 -1
  636. package/src/commands/source.js +0 -39
  637. package/src/commands/stat.d.ts.map +0 -1
  638. package/src/commands/stat.js +0 -56
  639. package/src/commands/su.d.ts.map +0 -1
  640. package/src/commands/su.js +0 -57
  641. package/src/commands/sudo.d.ts.map +0 -1
  642. package/src/commands/sudo.js +0 -54
  643. package/src/commands/tail.d.ts.map +0 -1
  644. package/src/commands/tail.js +0 -47
  645. package/src/commands/tar.d.ts.map +0 -1
  646. package/src/commands/tar.js +0 -102
  647. package/src/commands/tee.d.ts.map +0 -1
  648. package/src/commands/tee.js +0 -36
  649. package/src/commands/test.d.ts.map +0 -1
  650. package/src/commands/test.js +0 -114
  651. package/src/commands/touch.d.ts.map +0 -1
  652. package/src/commands/touch.js +0 -25
  653. package/src/commands/tr.d.ts.map +0 -1
  654. package/src/commands/tr.js +0 -61
  655. package/src/commands/tree.d.ts.map +0 -1
  656. package/src/commands/tree.js +0 -18
  657. package/src/commands/true.d.ts.map +0 -1
  658. package/src/commands/true.js +0 -24
  659. package/src/commands/type.d.ts.map +0 -1
  660. package/src/commands/type.js +0 -39
  661. package/src/commands/uname.d.ts.map +0 -1
  662. package/src/commands/uname.js +0 -29
  663. package/src/commands/uniq.d.ts.map +0 -1
  664. package/src/commands/uniq.js +0 -38
  665. package/src/commands/unset.d.ts.map +0 -1
  666. package/src/commands/unset.js +0 -16
  667. package/src/commands/uptime.d.ts.map +0 -1
  668. package/src/commands/uptime.js +0 -48
  669. package/src/commands/wc.d.ts.map +0 -1
  670. package/src/commands/wc.js +0 -55
  671. package/src/commands/wget.d.ts.map +0 -1
  672. package/src/commands/wget.js +0 -126
  673. package/src/commands/which.d.ts.map +0 -1
  674. package/src/commands/which.js +0 -32
  675. package/src/commands/who.d.ts.map +0 -1
  676. package/src/commands/who.js +0 -22
  677. package/src/commands/whoami.d.ts.map +0 -1
  678. package/src/commands/whoami.js +0 -12
  679. package/src/commands/xargs.d.ts.map +0 -1
  680. package/src/commands/xargs.js +0 -21
  681. package/src/index.d.ts.map +0 -1
  682. package/src/index.js +0 -9
  683. package/src/modules/linuxRootfs.d.ts.map +0 -1
  684. package/src/modules/linuxRootfs.js +0 -619
  685. package/src/modules/neofetch.d.ts.map +0 -1
  686. package/src/modules/neofetch.js +0 -284
  687. package/src/modules/shellInteractive.d.ts.map +0 -1
  688. package/src/modules/shellInteractive.js +0 -26
  689. package/src/modules/shellRuntime.d.ts.map +0 -1
  690. package/src/modules/shellRuntime.js +0 -52
  691. package/src/self-standalone.d.ts.map +0 -1
  692. package/src/self-standalone.js +0 -418
  693. package/src/standalone-wo-sftp.d.ts.map +0 -1
  694. package/src/standalone-wo-sftp.js +0 -30
  695. package/src/standalone.d.ts.map +0 -1
  696. package/src/standalone.js +0 -35
  697. package/src/types/commands.d.ts.map +0 -1
  698. package/src/types/commands.js +0 -0
  699. package/src/types/pipeline.d.ts.map +0 -1
  700. package/src/types/pipeline.js +0 -0
  701. package/src/types/streams.d.ts.map +0 -1
  702. package/src/types/streams.js +0 -0
  703. package/src/types/vfs.d.ts.map +0 -1
  704. package/src/types/vfs.js +0 -0
  705. package/src/utils/expand.d.ts.map +0 -1
  706. package/src/utils/expand.js +0 -476
  707. package/src/utils/perfLogger.d.ts.map +0 -1
  708. package/src/utils/perfLogger.js +0 -49
  709. package/src/utils/tokenize.d.ts.map +0 -1
  710. package/src/utils/tokenize.js +0 -114
  711. package/src/utils/vfsDiff.d.ts.map +0 -1
  712. package/src/utils/vfsDiff.js +0 -177
  713. package/src/web-api.d.ts.map +0 -1
  714. package/src/web-api.js +0 -46
  715. package/src/web-full.d.ts.map +0 -1
  716. package/src/web-full.js +0 -8
  717. package/src/web.d.ts.map +0 -1
  718. package/src/web.js +0 -773
  719. package/tests/command-helpers.test.d.ts +0 -2
  720. package/tests/command-helpers.test.d.ts.map +0 -1
  721. package/tests/command-helpers.test.js +0 -92
  722. package/tests/commands-admin-net.test.d.ts +0 -2
  723. package/tests/commands-admin-net.test.d.ts.map +0 -1
  724. package/tests/commands-admin-net.test.js +0 -353
  725. package/tests/commands-advanced.test.d.ts +0 -2
  726. package/tests/commands-advanced.test.d.ts.map +0 -1
  727. package/tests/commands-advanced.test.js +0 -378
  728. package/tests/commands-core.test.d.ts +0 -2
  729. package/tests/commands-core.test.d.ts.map +0 -1
  730. package/tests/commands-core.test.js +0 -477
  731. package/tests/commands-missing.test.d.ts +0 -2
  732. package/tests/commands-missing.test.d.ts.map +0 -1
  733. package/tests/commands-missing.test.js +0 -470
  734. package/tests/commands-specific-units.test.d.ts +0 -2
  735. package/tests/commands-specific-units.test.d.ts.map +0 -1
  736. package/tests/commands-specific-units.test.js +0 -264
  737. package/tests/commands-text-sys.test.d.ts +0 -2
  738. package/tests/commands-text-sys.test.d.ts.map +0 -1
  739. package/tests/commands-text-sys.test.js +0 -366
  740. package/tests/expand.test.d.ts +0 -2
  741. package/tests/expand.test.d.ts.map +0 -1
  742. package/tests/expand.test.js +0 -138
  743. package/tests/helpers.test.d.ts +0 -2
  744. package/tests/helpers.test.d.ts.map +0 -1
  745. package/tests/helpers.test.js +0 -52
  746. package/tests/new-features.test.d.ts +0 -2
  747. package/tests/new-features.test.d.ts.map +0 -1
  748. package/tests/new-features.test.js +0 -850
  749. package/tests/parser-executor.test.d.ts +0 -2
  750. package/tests/parser-executor.test.d.ts.map +0 -1
  751. package/tests/parser-executor.test.js +0 -25
  752. package/tests/sftp.test.d.ts +0 -2
  753. package/tests/sftp.test.d.ts.map +0 -1
  754. package/tests/sftp.test.js +0 -246
  755. package/tests/ssh-exec.test.d.ts +0 -2
  756. package/tests/ssh-exec.test.d.ts.map +0 -1
  757. package/tests/ssh-exec.test.js +0 -39
  758. package/tests/test-helper.d.ts +0 -56
  759. package/tests/test-helper.d.ts.map +0 -1
  760. package/tests/test-helper.js +0 -71
  761. package/tests/users.test.d.ts +0 -2
  762. package/tests/users.test.d.ts.map +0 -1
  763. package/tests/users.test.js +0 -71
  764. package/tests/web.test.d.ts +0 -2
  765. package/tests/web.test.d.ts.map +0 -1
  766. package/tests/web.test.js +0 -149
  767. /package/{src → dist}/Honeypot/index.d.ts +0 -0
  768. /package/{src → dist}/SSHClient/index.d.ts +0 -0
  769. /package/{src → dist}/SSHMimic/exec.d.ts +0 -0
  770. /package/{src → dist}/SSHMimic/executor.d.ts +0 -0
  771. /package/{src → dist}/SSHMimic/hostKey.d.ts +0 -0
  772. /package/{src → dist}/SSHMimic/index.d.ts +0 -0
  773. /package/{src → dist}/SSHMimic/loginBanner.d.ts +0 -0
  774. /package/{src → dist}/SSHMimic/loginFormat.d.ts +0 -0
  775. /package/{src → dist}/SSHMimic/prompt.d.ts +0 -0
  776. /package/{src → dist}/SSHMimic/sftp.d.ts +0 -0
  777. /package/{src → dist}/VirtualFileSystem/binaryPack.d.ts +0 -0
  778. /package/{src → dist}/VirtualFileSystem/index.d.ts +0 -0
  779. /package/{src → dist}/VirtualFileSystem/internalTypes.d.ts +0 -0
  780. /package/{src → dist}/VirtualFileSystem/path.d.ts +0 -0
  781. /package/{src → dist}/VirtualPackageManager/index.d.ts +0 -0
  782. /package/{src → dist}/VirtualShell/index.d.ts +0 -0
  783. /package/{src → dist}/VirtualShell/shell.d.ts +0 -0
  784. /package/{src → dist}/VirtualShell/shellParser.d.ts +0 -0
  785. /package/{src → dist}/VirtualUserManager/index.d.ts +0 -0
  786. /package/{src → dist}/commands/adduser.d.ts +0 -0
  787. /package/{src → dist}/commands/alias.d.ts +0 -0
  788. /package/{src → dist}/commands/apt.d.ts +0 -0
  789. /package/{src → dist}/commands/awk.d.ts +0 -0
  790. /package/{src → dist}/commands/base64.d.ts +0 -0
  791. /package/{src → dist}/commands/cat.d.ts +0 -0
  792. /package/{src → dist}/commands/cd.d.ts +0 -0
  793. /package/{src → dist}/commands/chmod.d.ts +0 -0
  794. /package/{src → dist}/commands/clear.d.ts +0 -0
  795. /package/{src → dist}/commands/command-helpers.d.ts +0 -0
  796. /package/{src → dist}/commands/cp.d.ts +0 -0
  797. /package/{src → dist}/commands/curl.d.ts +0 -0
  798. /package/{src → dist}/commands/cut.d.ts +0 -0
  799. /package/{src → dist}/commands/date.d.ts +0 -0
  800. /package/{src → dist}/commands/declare.d.ts +0 -0
  801. /package/{src → dist}/commands/deluser.d.ts +0 -0
  802. /package/{src → dist}/commands/df.d.ts +0 -0
  803. /package/{src → dist}/commands/diff.d.ts +0 -0
  804. /package/{src → dist}/commands/dpkg.d.ts +0 -0
  805. /package/{src → dist}/commands/du.d.ts +0 -0
  806. /package/{src → dist}/commands/echo.d.ts +0 -0
  807. /package/{src → dist}/commands/env.d.ts +0 -0
  808. /package/{src → dist}/commands/exit.d.ts +0 -0
  809. /package/{src → dist}/commands/export.d.ts +0 -0
  810. /package/{src → dist}/commands/find.d.ts +0 -0
  811. /package/{src → dist}/commands/free.d.ts +0 -0
  812. /package/{src → dist}/commands/grep.d.ts +0 -0
  813. /package/{src → dist}/commands/groups.d.ts +0 -0
  814. /package/{src → dist}/commands/gzip.d.ts +0 -0
  815. /package/{src → dist}/commands/head.d.ts +0 -0
  816. /package/{src → dist}/commands/help.d.ts +0 -0
  817. /package/{src → dist}/commands/helpers.d.ts +0 -0
  818. /package/{src → dist}/commands/history.d.ts +0 -0
  819. /package/{src → dist}/commands/hostname.d.ts +0 -0
  820. /package/{src → dist}/commands/htop.d.ts +0 -0
  821. /package/{src → dist}/commands/id.d.ts +0 -0
  822. /package/{src → dist}/commands/index.d.ts +0 -0
  823. /package/{src → dist}/commands/kill.d.ts +0 -0
  824. /package/{src → dist}/commands/ln.d.ts +0 -0
  825. /package/{src → dist}/commands/ls.d.ts +0 -0
  826. /package/{src → dist}/commands/lsb-release.d.ts +0 -0
  827. /package/{src → dist}/commands/man.d.ts +0 -0
  828. /package/{src → dist}/commands/mkdir.d.ts +0 -0
  829. /package/{src → dist}/commands/mv.d.ts +0 -0
  830. /package/{src → dist}/commands/nano.d.ts +0 -0
  831. /package/{src → dist}/commands/neofetch.d.ts +0 -0
  832. /package/{src → dist}/commands/node.d.ts +0 -0
  833. /package/{src → dist}/commands/npm.d.ts +0 -0
  834. /package/{src → dist}/commands/passwd.d.ts +0 -0
  835. /package/{src → dist}/commands/ping.d.ts +0 -0
  836. /package/{src → dist}/commands/printf.d.ts +0 -0
  837. /package/{src → dist}/commands/ps.d.ts +0 -0
  838. /package/{src → dist}/commands/pwd.d.ts +0 -0
  839. /package/{src → dist}/commands/python.d.ts +0 -0
  840. /package/{src → dist}/commands/read.d.ts +0 -0
  841. /package/{src → dist}/commands/registry.d.ts +0 -0
  842. /package/{src → dist}/commands/rm.d.ts +0 -0
  843. /package/{src → dist}/commands/runtime.d.ts +0 -0
  844. /package/{src → dist}/commands/sed.d.ts +0 -0
  845. /package/{src → dist}/commands/seq.d.ts +0 -0
  846. /package/{src → dist}/commands/set.d.ts +0 -0
  847. /package/{src → dist}/commands/sh.d.ts +0 -0
  848. /package/{src → dist}/commands/shift.d.ts +0 -0
  849. /package/{src → dist}/commands/sleep.d.ts +0 -0
  850. /package/{src → dist}/commands/sort.d.ts +0 -0
  851. /package/{src → dist}/commands/source.d.ts +0 -0
  852. /package/{src → dist}/commands/stat.d.ts +0 -0
  853. /package/{src → dist}/commands/su.d.ts +0 -0
  854. /package/{src → dist}/commands/sudo.d.ts +0 -0
  855. /package/{src → dist}/commands/tail.d.ts +0 -0
  856. /package/{src → dist}/commands/tar.d.ts +0 -0
  857. /package/{src → dist}/commands/tee.d.ts +0 -0
  858. /package/{src → dist}/commands/test.d.ts +0 -0
  859. /package/{src → dist}/commands/touch.d.ts +0 -0
  860. /package/{src → dist}/commands/tr.d.ts +0 -0
  861. /package/{src → dist}/commands/tree.d.ts +0 -0
  862. /package/{src → dist}/commands/true.d.ts +0 -0
  863. /package/{src → dist}/commands/type.d.ts +0 -0
  864. /package/{src → dist}/commands/uname.d.ts +0 -0
  865. /package/{src → dist}/commands/uniq.d.ts +0 -0
  866. /package/{src → dist}/commands/unset.d.ts +0 -0
  867. /package/{src → dist}/commands/uptime.d.ts +0 -0
  868. /package/{src → dist}/commands/wc.d.ts +0 -0
  869. /package/{src → dist}/commands/wget.d.ts +0 -0
  870. /package/{src → dist}/commands/which.d.ts +0 -0
  871. /package/{src → dist}/commands/who.d.ts +0 -0
  872. /package/{src → dist}/commands/whoami.d.ts +0 -0
  873. /package/{src → dist}/commands/xargs.d.ts +0 -0
  874. /package/{src → dist}/index.d.ts +0 -0
  875. /package/{src → dist}/modules/linuxRootfs.d.ts +0 -0
  876. /package/{src → dist}/modules/neofetch.d.ts +0 -0
  877. /package/{src → dist}/modules/shellInteractive.d.ts +0 -0
  878. /package/{src → dist}/modules/shellRuntime.d.ts +0 -0
  879. /package/{src → dist}/self-standalone.d.ts +0 -0
  880. /package/{src → dist}/standalone-wo-sftp.d.ts +0 -0
  881. /package/{src → dist}/standalone.d.ts +0 -0
  882. /package/{src → dist}/types/commands.d.ts +0 -0
  883. /package/{src → dist}/types/pipeline.d.ts +0 -0
  884. /package/{src → dist}/types/streams.d.ts +0 -0
  885. /package/{src → dist}/types/vfs.d.ts +0 -0
  886. /package/{src → dist}/utils/expand.d.ts +0 -0
  887. /package/{src → dist}/utils/perfLogger.d.ts +0 -0
  888. /package/{src → dist}/utils/tokenize.d.ts +0 -0
  889. /package/{src → dist}/utils/vfsDiff.d.ts +0 -0
  890. /package/{src → dist}/web-api.d.ts +0 -0
  891. /package/{src → dist}/web-full.d.ts +0 -0
  892. /package/{src → dist}/web.d.ts +0 -0
@@ -0,0 +1,1842 @@
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>typescript-virtual-container</title><meta name="description" content="Documentation for typescript-virtual-container"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="index.html" class="title">typescript-virtual-container</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><h1>typescript-virtual-container</h1></div><div class="tsd-panel tsd-typography"><h1 id="_" class="tsd-anchor-link"><code>typescript-virtual-container</code><a href="#_" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1>
2
+ <blockquote>
3
+ <p>A complete virtual Linux environment in pure TypeScript — runs as an SSH/SFTP server, a browser-based web shell, or a standalone CLI. Ships with a realistic Linux rootfs, a virtual package manager, a full shell interpreter, and a typed programmatic API for testing, automation, honeypots, and embedded shell experiences.</p>
4
+ </blockquote>
5
+ <p><a href="https://www.npmjs.com/package/typescript-virtual-container"><img src="https://badge.fury.io/js/typescript-virtual-container.svg" alt="npm version"></a>
6
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
7
+ <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.x-3178C6.svg?logo=typescript&amp;logoColor=white" alt="TypeScript"></a>
8
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/runtime-Node.js%20%7C%20Bun-43853D.svg" alt="Runtime"></a></p>
9
+ <hr>
10
+ <h2 id="table-of-contents" class="tsd-anchor-link">Table of Contents<a href="#table-of-contents" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
11
+ <ul>
12
+ <li><a href="#three-ways-to-run">Three ways to run</a></li>
13
+ <li><a href="#get-started">Get Started</a>
14
+ <ul>
15
+ <li><a href="#install">Install</a></li>
16
+ <li><a href="#try-instantly-zero-install">Try instantly (zero install)</a></li>
17
+ <li><a href="#ssh-server">SSH server</a></li>
18
+ <li><a href="#web-shell-browser">Web shell (browser)</a></li>
19
+ <li><a href="#programmatic-api">Programmatic API</a></li>
20
+ </ul>
21
+ </li>
22
+ <li><a href="#how-it-works">How It Works</a></li>
23
+ <li><a href="#api-reference">API Reference</a> <em>(open by default)</em>
24
+ <ul>
25
+ <li><a href="#virtualsshserver"><code>VirtualSshServer</code></a></li>
26
+ <li><a href="#virtualsftpserver"><code>VirtualSftpServer</code></a></li>
27
+ <li><a href="#virtualshell"><code>VirtualShell</code></a></li>
28
+ <li><a href="#virtualfilesystem"><code>VirtualFileSystem</code></a>
29
+ <ul>
30
+ <li><a href="#mount-api">Mount API</a></li>
31
+ </ul>
32
+ </li>
33
+ <li><a href="#virtualusermanager"><code>VirtualUserManager</code></a></li>
34
+ <li><a href="#virtualpackagemanager"><code>VirtualPackageManager</code></a></li>
35
+ <li><a href="#snapshot-diff-tooling">Snapshot Diff Tooling</a></li>
36
+ <li><a href="#honeypot"><code>HoneyPot</code></a></li>
37
+ <li><a href="#sshclient-programmatic-api"><code>SshClient</code></a></li>
38
+ <li><a href="#key-types">Key Types</a></li>
39
+ <li><a href="#command-helpers">Command Helpers</a></li>
40
+ </ul>
41
+ </li>
42
+ <li><a href="#examples">Examples</a></li>
43
+ <li><a href="#built-in-commands-91">Built-in Commands (91)</a></li>
44
+ <li><a href="#shell-scripting">Shell Scripting</a></li>
45
+ <li><a href="#linux-rootfs--vfs-path-resolution">Linux Rootfs &amp; VFS PATH Resolution</a></li>
46
+ <li><a href="#configuration">Configuration</a></li>
47
+ <li><a href="#performance--scalability">Performance &amp; Scalability</a></li>
48
+ <li><a href="#types--typescript">Types &amp; TypeScript</a></li>
49
+ <li><a href="#troubleshooting">Troubleshooting</a></li>
50
+ <li><a href="#faq">FAQ</a></li>
51
+ <li><a href="#contributing">Contributing</a></li>
52
+ <li><a href="#security">Security</a></li>
53
+ <li><a href="#compatibility">Compatibility</a></li>
54
+ <li><a href="#license">License</a></li>
55
+ <li><a href="#roadmap">Roadmap</a></li>
56
+ </ul>
57
+ <hr>
58
+ <h2 id="three-ways-to-run" class="tsd-anchor-link">Three ways to run<a href="#three-ways-to-run" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
59
+ <table>
60
+ <thead>
61
+ <tr>
62
+ <th>Mode</th>
63
+ <th>Entry point</th>
64
+ <th>Use case</th>
65
+ </tr>
66
+ </thead>
67
+ <tbody>
68
+ <tr>
69
+ <td><strong>SSH/SFTP server</strong></td>
70
+ <td><code>VirtualSshServer</code> / <code>VirtualSftpServer</code></td>
71
+ <td>Honeypots, remote testing, training environments</td>
72
+ </tr>
73
+ <tr>
74
+ <td><strong>Web shell</strong></td>
75
+ <td><code>builds/web.min.js</code> / <code>builds/web-full-api.min.js</code> (ESM)</td>
76
+ <td>Embedded terminals, interactive tutorials, browser demos</td>
77
+ </tr>
78
+ <tr>
79
+ <td><strong>Standalone CLI</strong></td>
80
+ <td><code>builds/self-standalone.js</code> (single file)</td>
81
+ <td>Local shell, one-liner demos, no install required</td>
82
+ </tr>
83
+ </tbody>
84
+ </table>
85
+ <p>All three modes share the same core: a pure in-memory VFS, a real shell interpreter, a virtual package manager, and a typed programmatic API.</p>
86
+ <hr>
87
+ <h2 id="get-started" class="tsd-anchor-link">Get Started<a href="#get-started" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
88
+ <h3 id="install" class="tsd-anchor-link">Install<a href="#install" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
89
+ <pre><code class="bash"><span class="hl-0">npm</span><span class="hl-1"> </span><span class="hl-2">install</span><span class="hl-1"> </span><span class="hl-2">typescript-virtual-container</span><br/><span class="hl-3"># or: yarn add / bun add</span>
90
+ </code><button type="button">Copy</button></pre>
91
+
92
+ <h3 id="try-instantly-zero-install" class="tsd-anchor-link">Try instantly (zero install)<a href="#try-instantly-zero-install" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
93
+ <pre><code class="bash"><span class="hl-3"># Interactive local shell — persists VFS in .vfs/ in the current directory</span><br/><span class="hl-0">curl</span><span class="hl-1"> </span><span class="hl-4">-s</span><span class="hl-1"> </span><span class="hl-2">https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/self-standalone.js</span><span class="hl-1"> </span><span class="hl-4">-o</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">rm</span><span class="hl-1"> </span><span class="hl-4">-f</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><br/><br/><span class="hl-3"># SSH server (connect with any SSH client on port 2222)</span><br/><span class="hl-0">curl</span><span class="hl-1"> </span><span class="hl-4">-s</span><span class="hl-1"> </span><span class="hl-2">https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/standalone.js</span><span class="hl-1"> </span><span class="hl-4">-o</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">rm</span><span class="hl-1"> </span><span class="hl-4">-f</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span><br/><br/><span class="hl-3"># SSH server without SFTP (lighter build)</span><br/><span class="hl-0">curl</span><span class="hl-1"> </span><span class="hl-4">-s</span><span class="hl-1"> </span><span class="hl-2">https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/standalone-wo-sftp.js</span><span class="hl-1"> </span><span class="hl-4">-o</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">rm</span><span class="hl-1"> </span><span class="hl-4">-f</span><span class="hl-1"> </span><span class="hl-2">standalone.js</span>
94
+ </code><button type="button">Copy</button></pre>
95
+
96
+ <div class="tsd-alert tsd-alert-note"><div class="tsd-alert-title"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><use href="assets/icons.svg#icon-alertNote"></use></svg><span>Note</span></div><p>
97
+ The standalone builds are intended for quick demos and testing. For production use, it's recommended to install the package and import the relevant classes directly in your codebase for better performance, stability, and security.
98
+ It implies command <code>man</code> is not available in standalone mode because manuals are not included in the minimal build, but you can always refer to the <a href="#api-reference">API Reference</a> for detailed documentation.</p>
99
+ </div>
100
+ <p><strong><code>self-standalone.js</code> options:</strong></p>
101
+ <pre><code class="bash"><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> </span><span class="hl-3"># boot as root</span><br/><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> </span><span class="hl-4">--user</span><span class="hl-1"> </span><span class="hl-2">alice</span><span class="hl-1"> </span><span class="hl-3"># boot as alice (prompts for password if set)</span><br/><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> </span><span class="hl-4">--user=alice</span><span class="hl-1"> </span><span class="hl-3"># same, inline form</span><br/><span class="hl-5">SSH_MIMIC_HOSTNAME</span><span class="hl-1">=</span><span class="hl-2">my-box</span><span class="hl-1"> </span><span class="hl-0">node</span><span class="hl-1"> </span><span class="hl-2">self-standalone.js</span><span class="hl-1"> </span><span class="hl-3"># custom hostname</span>
102
+ </code><button type="button">Copy</button></pre>
103
+
104
+ <p>The VFS is persisted automatically to <code>.vfs/vfs-snapshot.vfsb</code> in the current directory — state survives between runs. Delete <code>.vfs/</code> to start fresh.</p>
105
+ <p>The shell shows a login banner and <code>Last login:</code> timestamp on each start.</p>
106
+ <h3 id="ssh-server" class="tsd-anchor-link">SSH server<a href="#ssh-server" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
107
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">VirtualSshServer</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">hostname:</span><span class="hl-1"> </span><span class="hl-2">&quot;my-container&quot;</span><span class="hl-1"> });</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><span class="hl-3">// ssh root@localhost -p 2222</span>
108
+ </code><button type="button">Copy</button></pre>
109
+
110
+ <h3 id="web-shell-browser" class="tsd-anchor-link">Web shell (browser)<a href="#web-shell-browser" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
111
+ <p>Two browser bundles are available:</p>
112
+ <table>
113
+ <thead>
114
+ <tr>
115
+ <th>Bundle</th>
116
+ <th>Format</th>
117
+ <th>Entry point</th>
118
+ <th>Use case</th>
119
+ </tr>
120
+ </thead>
121
+ <tbody>
122
+ <tr>
123
+ <td><code>builds/web.min.js</code></td>
124
+ <td>ESM</td>
125
+ <td><code>createWebShell()</code></td>
126
+ <td>Embedded terminals, modern bundlers</td>
127
+ </tr>
128
+ <tr>
129
+ <td><code>builds/web-full-api.min.js</code></td>
130
+ <td>ESM</td>
131
+ <td><code>createVirtualShellShim()</code></td>
132
+ <td>Full <code>VirtualShell</code>-like API in the browser</td>
133
+ </tr>
134
+ </tbody>
135
+ </table>
136
+ <p>Both bundles persist the VFS in <strong>IndexedDB</strong> — state survives page reloads.</p>
137
+ <pre><code class="bash"><span class="hl-0">bun</span><span class="hl-1"> </span><span class="hl-2">run</span><span class="hl-1"> </span><span class="hl-2">web-build</span><span class="hl-1"> </span><span class="hl-3"># → builds/web.min.js + examples/web.min.js</span><br/><span class="hl-0">bun</span><span class="hl-1"> </span><span class="hl-2">run</span><span class="hl-1"> </span><span class="hl-2">web-full-build</span><span class="hl-1"> </span><span class="hl-3"># → builds/web-full-api.min.js</span><br/><span class="hl-0">bun</span><span class="hl-1"> </span><span class="hl-2">run</span><span class="hl-1"> </span><span class="hl-2">build-all</span><span class="hl-1"> </span><span class="hl-3"># rebuild everything</span>
138
+ </code><button type="button">Copy</button></pre>
139
+
140
+ <p><strong><code>web.min.js</code></strong> — lightweight shell with IndexedDB VFS:</p>
141
+ <pre><code class="html"><span class="hl-9">&lt;</span><span class="hl-10">script</span><span class="hl-11"> </span><span class="hl-12">type</span><span class="hl-11">=</span><span class="hl-13">&quot;module&quot;</span><span class="hl-9">&gt;</span><br/><span class="hl-11"> </span><span class="hl-6">import</span><span class="hl-11"> { </span><span class="hl-5">createWebShell</span><span class="hl-11"> } </span><span class="hl-6">from</span><span class="hl-11"> </span><span class="hl-2">&quot;./builds/web.min.js&quot;</span><span class="hl-11">;</span><br/><br/><span class="hl-11"> </span><span class="hl-4">const</span><span class="hl-11"> </span><span class="hl-7">shell</span><span class="hl-11"> </span><span class="hl-1">=</span><span class="hl-11"> </span><span class="hl-0">createWebShell</span><span class="hl-11">(</span><span class="hl-2">&quot;web-vm&quot;</span><span class="hl-11">, {</span><br/><span class="hl-11"> </span><span class="hl-5">vfs:</span><span class="hl-11"> { </span><span class="hl-5">databaseName:</span><span class="hl-11"> </span><span class="hl-2">&quot;virtual-env-js&quot;</span><span class="hl-11">, </span><span class="hl-5">storeName:</span><span class="hl-11"> </span><span class="hl-2">&quot;vfs&quot;</span><span class="hl-11"> },</span><br/><span class="hl-11"> });</span><br/><span class="hl-11"> </span><span class="hl-6">await</span><span class="hl-11"> </span><span class="hl-5">shell</span><span class="hl-11">.</span><span class="hl-0">ensureInitialized</span><span class="hl-11">();</span><br/><br/><span class="hl-11"> </span><span class="hl-4">const</span><span class="hl-11"> </span><span class="hl-7">out</span><span class="hl-11"> </span><span class="hl-1">=</span><span class="hl-11"> </span><span class="hl-6">await</span><span class="hl-11"> </span><span class="hl-5">shell</span><span class="hl-11">.</span><span class="hl-0">executeCommandLine</span><span class="hl-11">(</span><span class="hl-2">&quot;ls /etc &amp;&amp; echo hello&quot;</span><span class="hl-11">);</span><br/><span class="hl-11"> </span><span class="hl-5">console</span><span class="hl-11">.</span><span class="hl-0">log</span><span class="hl-11">(</span><span class="hl-5">out</span><span class="hl-11">.</span><span class="hl-5">stdout</span><span class="hl-11">);</span><br/><span class="hl-9">&lt;/</span><span class="hl-10">script</span><span class="hl-9">&gt;</span>
142
+ </code><button type="button">Copy</button></pre>
143
+
144
+ <p><strong><code>web-full-api.min.js</code></strong> — mirrors the <code>VirtualShell</code> programmatic API:</p>
145
+ <pre><code class="html"><span class="hl-9">&lt;</span><span class="hl-10">script</span><span class="hl-11"> </span><span class="hl-12">type</span><span class="hl-11">=</span><span class="hl-13">&quot;module&quot;</span><span class="hl-9">&gt;</span><br/><span class="hl-11"> </span><span class="hl-6">import</span><span class="hl-11"> { </span><span class="hl-5">createVirtualShellShim</span><span class="hl-11"> } </span><span class="hl-6">from</span><span class="hl-11"> </span><span class="hl-2">&quot;./builds/web-full-api.min.js&quot;</span><span class="hl-11">;</span><br/><br/><span class="hl-11"> </span><span class="hl-4">const</span><span class="hl-11"> </span><span class="hl-7">shell</span><span class="hl-11"> </span><span class="hl-1">=</span><span class="hl-11"> </span><span class="hl-0">createVirtualShellShim</span><span class="hl-11">(</span><span class="hl-2">&quot;web-vm&quot;</span><span class="hl-11">);</span><br/><span class="hl-11"> </span><span class="hl-6">await</span><span class="hl-11"> </span><span class="hl-5">shell</span><span class="hl-11">.</span><span class="hl-0">ensureInitialized</span><span class="hl-11">();</span><br/><span class="hl-11"> </span><span class="hl-6">await</span><span class="hl-11"> </span><span class="hl-5">shell</span><span class="hl-11">.</span><span class="hl-0">executeCommandLine</span><span class="hl-11">(</span><span class="hl-2">&quot;mkdir -p /app &amp;&amp; echo hello &gt; /app/file.txt&quot;</span><span class="hl-11">);</span><br/><span class="hl-11"> </span><span class="hl-5">console</span><span class="hl-11">.</span><span class="hl-0">log</span><span class="hl-11">(</span><span class="hl-5">shell</span><span class="hl-11">.</span><span class="hl-0">getVfs</span><span class="hl-11">().</span><span class="hl-0">readFile</span><span class="hl-11">(</span><span class="hl-2">&quot;/app/file.txt&quot;</span><span class="hl-11">)); </span><span class="hl-3">// hello</span><br/><span class="hl-9">&lt;/</span><span class="hl-10">script</span><span class="hl-9">&gt;</span>
146
+ </code><button type="button">Copy</button></pre>
147
+
148
+ <p><strong>Run the demo locally:</strong></p>
149
+ <pre><code class="bash"><span class="hl-0">bun</span><span class="hl-1"> </span><span class="hl-2">run</span><span class="hl-1"> </span><span class="hl-2">example-serve</span><br/><span class="hl-3"># Open http://localhost:8787/index.html</span>
150
+ </code><button type="button">Copy</button></pre>
151
+
152
+ <h3 id="programmatic-api" class="tsd-anchor-link">Programmatic API<a href="#programmatic-api" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
153
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">SshClient</span><span class="hl-1">, </span><span class="hl-5">VirtualShell</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;typescript-vm&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">ensureInitialized</span><span class="hl-1">();</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">client</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;root&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">mkdir</span><span class="hl-1">(</span><span class="hl-2">&quot;/app/config&quot;</span><span class="hl-1">, </span><span class="hl-4">true</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/app/config/settings.json&quot;</span><span class="hl-1">, </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">stringify</span><span class="hl-1">({ </span><span class="hl-5">env:</span><span class="hl-1"> </span><span class="hl-2">&quot;dev&quot;</span><span class="hl-1"> }));</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">r</span><span class="hl-1"> = </span><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;ls /app &amp;&amp; cat /app/config/settings.json&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">r</span><span class="hl-1">.</span><span class="hl-5">stdout</span><span class="hl-1">);</span>
154
+ </code><button type="button">Copy</button></pre>
155
+
156
+ <hr>
157
+ <h2 id="how-it-works" class="tsd-anchor-link">How It Works<a href="#how-it-works" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
158
+ <pre><code><span class="hl-1">┌──────────────────────────────────────────────────────────────────────────┐</span><br/><span class="hl-1">│ </span><span class="hl-0">SshMimic</span><span class="hl-1"> (</span><span class="hl-5">VirtualSshServer</span><span class="hl-1">) </span><span class="hl-0">SftpMimic</span><span class="hl-1"> (</span><span class="hl-5">VirtualSftpServer</span><span class="hl-1">) │</span><br/><span class="hl-1">│ </span><span class="hl-5">password</span><span class="hl-1"> </span><span class="hl-5">auth</span><span class="hl-1"> · </span><span class="hl-5">publickey</span><span class="hl-1"> </span><span class="hl-5">auth</span><span class="hl-1"> </span><span class="hl-7">SFTP</span><span class="hl-1"> </span><span class="hl-5">protocol</span><span class="hl-1"> </span><span class="hl-5">handlers</span><span class="hl-1"> │</span><br/><span class="hl-1">│ </span><span class="hl-5">per</span><span class="hl-1">-</span><span class="hl-7">IP</span><span class="hl-1"> </span><span class="hl-5">rate</span><span class="hl-1"> </span><span class="hl-5">limiting</span><span class="hl-1"> / </span><span class="hl-5">lockout</span><span class="hl-1"> </span><span class="hl-5">home</span><span class="hl-1">-</span><span class="hl-5">dir</span><span class="hl-1"> </span><span class="hl-5">confinement</span><span class="hl-1"> │</span><br/><span class="hl-1">└─────────────────────────┬────────────────────────────────────────────────┘</span><br/><span class="hl-1"> │</span><br/><span class="hl-1"> ┌──────────▼──────────┐</span><br/><span class="hl-1"> │ </span><span class="hl-5">VirtualShell</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-5">script</span><span class="hl-1"> </span><span class="hl-5">parser</span><span class="hl-1"> │ ← &amp;&amp;</span><span class="hl-14">/</span><span class="hl-15">||</span><span class="hl-14">/</span><span class="hl-1">; · </span><span class="hl-6">if</span><span class="hl-1">/</span><span class="hl-5">for</span><span class="hl-1">/</span><span class="hl-6">while</span><span class="hl-1">/</span><span class="hl-6">case</span><br/><span class="hl-1"> │ </span><span class="hl-5">command</span><span class="hl-1"> </span><span class="hl-5">executor</span><span class="hl-1"> │ ← </span><span class="hl-5">per</span><span class="hl-1">-</span><span class="hl-5">session</span><span class="hl-1"> </span><span class="hl-5">ShellEnv</span><br/><span class="hl-1"> │ .</span><span class="hl-5">bashrc</span><span class="hl-1"> </span><span class="hl-5">loader</span><span class="hl-1"> │ ← </span><span class="hl-14">/home/</span><span class="hl-1">&lt;</span><span class="hl-5">user</span><span class="hl-1">&gt;/.</span><span class="hl-5">bashrc</span><br/><span class="hl-1"> │ </span><span class="hl-5">session</span><span class="hl-1"> </span><span class="hl-5">manager</span><span class="hl-1"> │</span><br/><span class="hl-1"> └──┬──────────────┬───┘</span><br/><span class="hl-1"> │ │</span><br/><span class="hl-1"> ┌────────────▼───┐ ┌─────▼───────────────┐</span><br/><span class="hl-1"> │</span><span class="hl-5">VirtualFileSystem</span><span class="hl-1">│ │ </span><span class="hl-5">VirtualUserManager</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-4">in</span><span class="hl-1">-</span><span class="hl-5">memory</span><span class="hl-1"> </span><span class="hl-5">tree</span><span class="hl-1"> │ │ </span><span class="hl-5">scrypt</span><span class="hl-1"> · </span><span class="hl-5">sudoers</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-5">gzip</span><span class="hl-1"> · </span><span class="hl-5">symlinks</span><span class="hl-1"> │ │ </span><span class="hl-5">publickey</span><span class="hl-1"> </span><span class="hl-5">auth</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ .</span><span class="hl-5">vfsb</span><span class="hl-1"> </span><span class="hl-5">binary</span><span class="hl-1"> │ │ </span><span class="hl-5">quotas</span><span class="hl-1"> · </span><span class="hl-5">sessions</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-16">mode</span><span class="hl-1">:</span><span class="hl-5">memory</span><span class="hl-1">|</span><span class="hl-5">fs</span><span class="hl-1"> │ └─────────────────────-┘</span><br/><span class="hl-1"> └─────────────────┘</span><br/><span class="hl-1"> │</span><br/><span class="hl-1"> ┌────────────▼────────────┐</span><br/><span class="hl-1"> │ </span><span class="hl-5">HoneyPot</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-5">audit</span><span class="hl-1"> </span><span class="hl-5">log</span><span class="hl-1"> · </span><span class="hl-5">stats</span><span class="hl-1"> │</span><br/><span class="hl-1"> │ </span><span class="hl-5">anomaly</span><span class="hl-1"> </span><span class="hl-5">detection</span><span class="hl-1"> │</span><br/><span class="hl-1"> └─────────────────────────┘</span>
159
+ </code><button>Copy</button></pre>
160
+
161
+ <p><strong>What it is:</strong> a shell emulator and virtual Linux environment for developer workflows.</p>
162
+ <p><strong>What it is not:</strong> a kernel-level security boundary. <code>curl</code>/<code>wget</code> use the native <code>fetch()</code> API — no host binary spawned. <code>node</code>/<code>python3</code>/<code>npm</code> are virtual REPL stubs, not real runtimes. <code>execvp</code> is never called. Do not expose to the public internet without additional isolation.</p>
163
+ <hr>
164
+ <details open>
165
+ <summary><strong>API Reference</strong></summary>
166
+ <h3 id="_-1" class="tsd-anchor-link"><code>VirtualSshServer</code><a href="#_-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
167
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-5">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">hostname</span><span class="hl-1">?: </span><span class="hl-5">string</span><span class="hl-1">; </span><span class="hl-3">// default: &quot;typescript-vm&quot;</span><br/><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">?: </span><span class="hl-5">VirtualShell</span><span class="hl-1">; </span><span class="hl-3">// share state with SFTP server</span><br/><span class="hl-1"> </span><span class="hl-5">maxAuthAttempts</span><span class="hl-1">?: </span><span class="hl-5">number</span><span class="hl-1">; </span><span class="hl-3">// default: 5</span><br/><span class="hl-1"> </span><span class="hl-5">lockoutDurationMs</span><span class="hl-1">?: </span><span class="hl-5">number</span><span class="hl-1">; </span><span class="hl-3">// default: 60_000</span><br/><span class="hl-1">})</span>
168
+ </code><button type="button">Copy</button></pre>
169
+
170
+ <p>If <code>shell</code> is omitted, the server creates <code>new VirtualShell(hostname)</code> internally.</p>
171
+ <p><strong>Methods</strong></p>
172
+ <table>
173
+ <thead>
174
+ <tr>
175
+ <th>Method</th>
176
+ <th>Description</th>
177
+ </tr>
178
+ </thead>
179
+ <tbody>
180
+ <tr>
181
+ <td><code>start(): Promise&lt;number&gt;</code></td>
182
+ <td>Initialize VFS, users, start listening. Returns bound port.</td>
183
+ </tr>
184
+ <tr>
185
+ <td><code>stop(): void</code></td>
186
+ <td>Gracefully close server and all active connections.</td>
187
+ </tr>
188
+ <tr>
189
+ <td><code>clearLockout(ip): void</code></td>
190
+ <td>Manually lift a rate-limit lockout for an IP.</td>
191
+ </tr>
192
+ <tr>
193
+ <td><code>getVfs(): VirtualFileSystem | null</code></td>
194
+ <td>Access VFS instance (null before start).</td>
195
+ </tr>
196
+ <tr>
197
+ <td><code>getUsers(): VirtualUserManager | null</code></td>
198
+ <td>Access user manager (null before start).</td>
199
+ </tr>
200
+ <tr>
201
+ <td><code>getHostname(): string</code></td>
202
+ <td>Returns configured hostname.</td>
203
+ </tr>
204
+ </tbody>
205
+ </table>
206
+ <p><strong>Events</strong></p>
207
+ <table>
208
+ <thead>
209
+ <tr>
210
+ <th>Event</th>
211
+ <th>Data</th>
212
+ <th>Description</th>
213
+ </tr>
214
+ </thead>
215
+ <tbody>
216
+ <tr>
217
+ <td><code>start</code></td>
218
+ <td><code>{ port }</code></td>
219
+ <td>Server started</td>
220
+ </tr>
221
+ <tr>
222
+ <td><code>stop</code></td>
223
+ <td>—</td>
224
+ <td>Server stopped</td>
225
+ </tr>
226
+ <tr>
227
+ <td><code>auth:success</code></td>
228
+ <td><code>{ username, remoteAddress, method? }</code></td>
229
+ <td>Authenticated</td>
230
+ </tr>
231
+ <tr>
232
+ <td><code>auth:failure</code></td>
233
+ <td><code>{ username, remoteAddress, reason?, method? }</code></td>
234
+ <td>Auth failed</td>
235
+ </tr>
236
+ <tr>
237
+ <td><code>auth:lockout</code></td>
238
+ <td><code>{ ip, until: Date }</code></td>
239
+ <td>IP locked out</td>
240
+ </tr>
241
+ <tr>
242
+ <td><code>client:connect</code></td>
243
+ <td>—</td>
244
+ <td>New SSH client connected</td>
245
+ </tr>
246
+ <tr>
247
+ <td><code>client:disconnect</code></td>
248
+ <td><code>{ user }</code></td>
249
+ <td>SSH client disconnected</td>
250
+ </tr>
251
+ </tbody>
252
+ </table>
253
+ <hr>
254
+ <h3 id="_-2" class="tsd-anchor-link"><code>VirtualSftpServer</code><a href="#_-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
255
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSftpServer</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-5">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">hostname</span><span class="hl-1">?: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">?: </span><span class="hl-5">VirtualShell</span><span class="hl-1">; </span><span class="hl-3">// share state with SSH server (recommended)</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">?: </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1">; </span><span class="hl-3">// explicit if no shell</span><br/><span class="hl-1"> </span><span class="hl-5">users</span><span class="hl-1">?: </span><span class="hl-5">VirtualUserManager</span><span class="hl-1">; </span><span class="hl-3">// explicit if no shell</span><br/><span class="hl-1">})</span>
256
+ </code><button type="button">Copy</button></pre>
257
+
258
+ <p>Supports <code>password</code> and <code>keyboard-interactive</code> auth. Confines all operations to <code>/home/&lt;user&gt;</code>. Unsupported operations return <code>OP_UNSUPPORTED</code>.</p>
259
+ <p><strong>Methods:</strong> <code>start(): Promise&lt;number&gt;</code>, <code>stop(): void</code></p>
260
+ <p><strong>Events:</strong> <code>start</code>, <code>stop</code>, <code>auth:success { username, remoteAddress }</code>, <code>auth:failure { username, remoteAddress }</code>, <code>client:connect</code>, <code>client:disconnect { user }</code></p>
261
+ <hr>
262
+ <h3 id="_-3" class="tsd-anchor-link"><code>VirtualShell</code><a href="#_-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
263
+ <p>Coordinates the VFS, user manager, package manager, and command runtime.</p>
264
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-5">hostname</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">properties</span><span class="hl-1">?: </span><span class="hl-5">ShellProperties</span><span class="hl-1">, </span><span class="hl-3">// kernel, os, arch — surfaced by uname/neofetch</span><br/><span class="hl-1"> </span><span class="hl-5">vfsOptions</span><span class="hl-1">?: </span><span class="hl-5">VfsOptions</span><span class="hl-1">, </span><span class="hl-3">// { mode: &quot;memory&quot;|&quot;fs&quot;, snapshotPath?: string }</span><br/><span class="hl-1">)</span>
265
+ </code><button type="button">Copy</button></pre>
266
+
267
+ <pre><code class="typescript"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">ShellProperties</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">kernel</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// e.g. &quot;1.0.0+itsrealfortune+1-amd64&quot;</span><br/><span class="hl-1"> </span><span class="hl-5">os</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// e.g. &quot;Fortune GNU/Linux x64&quot;</span><br/><span class="hl-1"> </span><span class="hl-5">arch</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// e.g. &quot;x86_64&quot;</span><br/><span class="hl-1">}</span>
268
+ </code><button type="button">Copy</button></pre>
269
+
270
+ <p><strong>Methods</strong></p>
271
+ <table>
272
+ <thead>
273
+ <tr>
274
+ <th>Method</th>
275
+ <th>Description</th>
276
+ </tr>
277
+ </thead>
278
+ <tbody>
279
+ <tr>
280
+ <td><code>ensureInitialized(): Promise&lt;void&gt;</code></td>
281
+ <td>Await before using programmatically.</td>
282
+ </tr>
283
+ <tr>
284
+ <td><code>addCommand(name, params, callback)</code></td>
285
+ <td>Register a custom shell command.</td>
286
+ </tr>
287
+ <tr>
288
+ <td><code>executeCommand(rawInput, authUser, cwd)</code></td>
289
+ <td>Run a raw command string.</td>
290
+ </tr>
291
+ <tr>
292
+ <td><code>startInteractiveSession(stream, authUser, sessionId, remoteAddress, terminalSize)</code></td>
293
+ <td>Attach a PTY session.</td>
294
+ </tr>
295
+ <tr>
296
+ <td><code>writeFileAsUser(authUser, path, content)</code></td>
297
+ <td>Write with quota enforcement.</td>
298
+ </tr>
299
+ <tr>
300
+ <td><code>refreshProcFs(): void</code></td>
301
+ <td>Refresh all <code>/proc/*</code> files (uptime, meminfo, cpuinfo, per-pid).</td>
302
+ </tr>
303
+ <tr>
304
+ <td><code>refreshProcSessions(): void</code></td>
305
+ <td>Lightweight refresh of <code>/proc/&lt;pid&gt;</code> and <code>/proc/self</code> only.</td>
306
+ </tr>
307
+ <tr>
308
+ <td><code>mount(vPath, hostPath, options?): void</code></td>
309
+ <td>Mount a host directory into the VFS. See <a href="#mount-api">Mount API</a>.</td>
310
+ </tr>
311
+ <tr>
312
+ <td><code>unmount(vPath): void</code></td>
313
+ <td>Remove a host directory mount.</td>
314
+ </tr>
315
+ <tr>
316
+ <td><code>getMounts()</code></td>
317
+ <td>List all active mounts as <code>{ vPath, hostPath, readOnly }[]</code>.</td>
318
+ </tr>
319
+ <tr>
320
+ <td><code>syncPasswd(): void</code></td>
321
+ <td>Sync <code>/etc/passwd</code>, <code>/etc/group</code>, <code>/etc/shadow</code> from user manager.</td>
322
+ </tr>
323
+ <tr>
324
+ <td><code>getVfs(): VirtualFileSystem | null</code></td>
325
+ <td>Access VFS instance.</td>
326
+ </tr>
327
+ <tr>
328
+ <td><code>getUsers(): VirtualUserManager | null</code></td>
329
+ <td>Access user manager.</td>
330
+ </tr>
331
+ <tr>
332
+ <td><code>getHostname(): string</code></td>
333
+ <td>Returns configured hostname.</td>
334
+ </tr>
335
+ </tbody>
336
+ </table>
337
+ <p><strong>Public fields</strong></p>
338
+ <table>
339
+ <thead>
340
+ <tr>
341
+ <th>Field</th>
342
+ <th>Type</th>
343
+ <th>Description</th>
344
+ </tr>
345
+ </thead>
346
+ <tbody>
347
+ <tr>
348
+ <td><code>vfs</code></td>
349
+ <td><code>VirtualFileSystem</code></td>
350
+ <td>Backing virtual filesystem.</td>
351
+ </tr>
352
+ <tr>
353
+ <td><code>users</code></td>
354
+ <td><code>VirtualUserManager</code></td>
355
+ <td>Virtual user database.</td>
356
+ </tr>
357
+ <tr>
358
+ <td><code>packageManager</code></td>
359
+ <td><code>VirtualPackageManager</code></td>
360
+ <td>APT/dpkg package manager.</td>
361
+ </tr>
362
+ <tr>
363
+ <td><code>hostname</code></td>
364
+ <td><code>string</code></td>
365
+ <td>Hostname shown in prompt and SSH ident.</td>
366
+ </tr>
367
+ <tr>
368
+ <td><code>properties</code></td>
369
+ <td><code>ShellProperties</code></td>
370
+ <td>Distro identity strings.</td>
371
+ </tr>
372
+ <tr>
373
+ <td><code>startTime</code></td>
374
+ <td><code>number</code></td>
375
+ <td>Unix ms timestamp of shell creation.</td>
376
+ </tr>
377
+ </tbody>
378
+ </table>
379
+ <p><strong>Events:</strong> <code>initialized</code>, <code>command { command, user, cwd }</code>, <code>session:start { user, sessionId, remoteAddress }</code></p>
380
+ <p><strong>Custom command example:</strong></p>
381
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">addCommand</span><span class="hl-1">(</span><span class="hl-2">&quot;greet&quot;</span><span class="hl-1">, [</span><span class="hl-2">&quot;[name]&quot;</span><span class="hl-1">], ({ </span><span class="hl-5">args</span><span class="hl-1">, </span><span class="hl-5">authUser</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">name</span><span class="hl-1"> = </span><span class="hl-5">args</span><span class="hl-1">[</span><span class="hl-8">0</span><span class="hl-1">] ?? </span><span class="hl-5">authUser</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">return</span><span class="hl-1"> { </span><span class="hl-5">stdout:</span><span class="hl-1"> </span><span class="hl-2">`Hello, </span><span class="hl-4">${</span><span class="hl-5">name</span><span class="hl-4">}</span><span class="hl-2">!</span><span class="hl-18">\n</span><span class="hl-2">`</span><span class="hl-1">, </span><span class="hl-5">exitCode:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1"> };</span><br/><span class="hl-1">});</span>
382
+ </code><button type="button">Copy</button></pre>
383
+
384
+ <hr>
385
+ <h3 id="_-4" class="tsd-anchor-link"><code>VirtualFileSystem</code><a href="#_-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
386
+ <p>Pure in-memory virtual filesystem. No host filesystem access at runtime.</p>
387
+ <pre><code class="typescript"><span class="hl-3">// Memory mode (default) — ephemeral</span><br/><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualFileSystem</span><span class="hl-1">()</span><br/><br/><span class="hl-3">// FS mode — persists to binary .vfsb file</span><br/><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualFileSystem</span><span class="hl-1">({ </span><span class="hl-5">mode:</span><span class="hl-1"> </span><span class="hl-2">&quot;fs&quot;</span><span class="hl-1">, </span><span class="hl-5">snapshotPath:</span><span class="hl-1"> </span><span class="hl-2">&quot;./data&quot;</span><span class="hl-1"> })</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">restoreMirror</span><span class="hl-1">(); </span><span class="hl-3">// load from disk (no-op if no file yet)</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">flushMirror</span><span class="hl-1">(); </span><span class="hl-3">// save to disk</span>
388
+ </code><button type="button">Copy</button></pre>
389
+
390
+ <p><strong>Methods</strong></p>
391
+ <table>
392
+ <thead>
393
+ <tr>
394
+ <th>Method</th>
395
+ <th>Description</th>
396
+ </tr>
397
+ </thead>
398
+ <tbody>
399
+ <tr>
400
+ <td><code>mkdir(path, mode?)</code></td>
401
+ <td>Create directory and any missing parents.</td>
402
+ </tr>
403
+ <tr>
404
+ <td><code>writeFile(path, content, options?)</code></td>
405
+ <td>Write file. <code>options.compress</code> gzips; <code>options.mode</code> sets POSIX mode bits.</td>
406
+ </tr>
407
+ <tr>
408
+ <td><code>readFile(path): string</code></td>
409
+ <td>Read as UTF-8. Transparently decompresses gzip.</td>
410
+ </tr>
411
+ <tr>
412
+ <td><code>readFileRaw(path): Buffer</code></td>
413
+ <td>Read as Buffer.</td>
414
+ </tr>
415
+ <tr>
416
+ <td><code>exists(path): boolean</code></td>
417
+ <td>Test existence.</td>
418
+ </tr>
419
+ <tr>
420
+ <td><code>stat(path): VfsNodeStats</code></td>
421
+ <td>Returns metadata.</td>
422
+ </tr>
423
+ <tr>
424
+ <td><code>list(path?): string[]</code></td>
425
+ <td>List direct children (sorted).</td>
426
+ </tr>
427
+ <tr>
428
+ <td><code>tree(path?): string</code></td>
429
+ <td>Render ASCII directory tree.</td>
430
+ </tr>
431
+ <tr>
432
+ <td><code>move(from, to)</code></td>
433
+ <td>Move or rename.</td>
434
+ </tr>
435
+ <tr>
436
+ <td><code>remove(path, options?)</code></td>
437
+ <td>Delete. <code>options.recursive</code> required for non-empty dirs.</td>
438
+ </tr>
439
+ <tr>
440
+ <td><code>chmod(path, mode)</code></td>
441
+ <td>Update POSIX mode bits.</td>
442
+ </tr>
443
+ <tr>
444
+ <td><code>compressFile(path)</code> / <code>decompressFile(path)</code></td>
445
+ <td>Gzip-compress / gunzip in place.</td>
446
+ </tr>
447
+ <tr>
448
+ <td><code>symlink(target, linkPath)</code></td>
449
+ <td>Create symbolic link.</td>
450
+ </tr>
451
+ <tr>
452
+ <td><code>isSymlink(path): boolean</code></td>
453
+ <td>Test if path is a symlink.</td>
454
+ </tr>
455
+ <tr>
456
+ <td><code>resolveSymlink(path, maxDepth?): string</code></td>
457
+ <td>Resolve symlink chain (default max 8 hops).</td>
458
+ </tr>
459
+ <tr>
460
+ <td><code>getUsageBytes(path?): number</code></td>
461
+ <td>Total stored bytes under a path.</td>
462
+ </tr>
463
+ <tr>
464
+ <td><code>toSnapshot(): VfsSnapshot</code></td>
465
+ <td>Export tree as JSON-serialisable snapshot.</td>
466
+ </tr>
467
+ <tr>
468
+ <td><code>importSnapshot(snapshot)</code></td>
469
+ <td>Replace current state from a snapshot.</td>
470
+ </tr>
471
+ <tr>
472
+ <td><code>restoreMirror(): Promise&lt;void&gt;</code></td>
473
+ <td>Load from disk (<code>&quot;fs&quot;</code> mode) / no-op otherwise.</td>
474
+ </tr>
475
+ <tr>
476
+ <td><code>flushMirror(): Promise&lt;void&gt;</code></td>
477
+ <td>Save to disk (<code>&quot;fs&quot;</code> mode) / emit event otherwise.</td>
478
+ </tr>
479
+ <tr>
480
+ <td><code>VirtualFileSystem.fromSnapshot(snapshot)</code></td>
481
+ <td><strong>Static.</strong> Create memory-mode instance from snapshot.</td>
482
+ </tr>
483
+ </tbody>
484
+ </table>
485
+ <p><strong>Events:</strong> <code>file:write { path, size }</code>, <code>file:read { path, size }</code>, <code>dir:create { path, mode }</code>, <code>node:remove { path }</code>, <code>symlink:create { link, target }</code>, <code>snapshot:import</code>, <code>snapshot:restore { path }</code>, <code>mirror:flush { path? }</code></p>
486
+ <h4 id="mount-api" class="tsd-anchor-link">Mount API<a href="#mount-api" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4>
487
+ <p>Mount a host directory inside the VM — all standard VFS operations (<code>readFile</code>, <code>writeFile</code>, <code>exists</code>, <code>stat</code>, <code>list</code>) are transparently delegated to the host filesystem.</p>
488
+ <blockquote>
489
+ <p><strong>Node.js only.</strong> In browser environments <code>mount()</code> is a silent no-op — the <code>vPath</code> remains an empty in-memory directory.</p>
490
+ </blockquote>
491
+ <pre><code class="typescript"><span class="hl-3">// Read-only mount (default) — shell commands can read host files</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">mount</span><span class="hl-1">(</span><span class="hl-2">&quot;/workspace&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;./my-project&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-3">// Read-write mount — shell commands can also write back to the host</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">mount</span><span class="hl-1">(</span><span class="hl-2">&quot;/data&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;./data&quot;</span><span class="hl-1">, { </span><span class="hl-5">readOnly:</span><span class="hl-1"> </span><span class="hl-4">false</span><span class="hl-1"> });</span><br/><br/><span class="hl-3">// Unmount — delegation removed, vPath stays as an empty VFS directory</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">unmount</span><span class="hl-1">(</span><span class="hl-2">&quot;/workspace&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-3">// Introspect</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">getMounts</span><span class="hl-1">();</span><br/><span class="hl-3">// → [{ vPath: &quot;/workspace&quot;, hostPath: &quot;/abs/path/my-project&quot;, readOnly: true }]</span>
492
+ </code><button type="button">Copy</button></pre>
493
+
494
+ <p>Direct VFS usage:</p>
495
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">mount</span><span class="hl-1">(</span><span class="hl-2">&quot;/workspace&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;./my-project&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">unmount</span><span class="hl-1">(</span><span class="hl-2">&quot;/workspace&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">getMounts</span><span class="hl-1">();</span>
496
+ </code><button type="button">Copy</button></pre>
497
+
498
+ <p><strong>Events:</strong> <code>mount { vPath, hostPath, readOnly }</code>, <code>unmount { vPath }</code></p>
499
+ <p><strong>Snapshot behaviour:</strong> mounted files are <strong>not</strong> included in <code>toSnapshot()</code> — only the in-memory VFS tree is serialised. The mount configuration itself is also not persisted; restore it after each <code>fromSnapshot()</code> or <code>restoreMirror()</code>.</p>
500
+ <h4 id="vfsb-binary-format" class="tsd-anchor-link">VFSB Binary Format<a href="#vfsb-binary-format" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4>
501
+ <p>In <code>&quot;fs&quot;</code> mode, state is persisted as a compact binary file (<code>vfs-snapshot.vfsb</code>).</p>
502
+ <table>
503
+ <thead>
504
+ <tr>
505
+ <th>Metric</th>
506
+ <th>JSON+base64</th>
507
+ <th>VFSB binary</th>
508
+ </tr>
509
+ </thead>
510
+ <tbody>
511
+ <tr>
512
+ <td>File size (10 MB content)</td>
513
+ <td>~13.7 MB</td>
514
+ <td>~10.0 MB</td>
515
+ </tr>
516
+ <tr>
517
+ <td>Encode time</td>
518
+ <td>~12 ms</td>
519
+ <td>~0.04 ms</td>
520
+ </tr>
521
+ <tr>
522
+ <td>Decode time</td>
523
+ <td>~18 ms</td>
524
+ <td>~0.07 ms</td>
525
+ </tr>
526
+ </tbody>
527
+ </table>
528
+ <p>Wire format: 5-byte header (<code>VFS!</code> magic + version), followed by a recursive node tree with type, name, mode, timestamps, and raw content bytes (no base64). Legacy JSON snapshots are auto-detected and migrated on first <code>flushMirror()</code>.</p>
529
+ <p>Low-level API:</p>
530
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">encodeVfs</span><span class="hl-1">, </span><span class="hl-5">decodeVfs</span><span class="hl-1">, </span><span class="hl-5">isBinarySnapshot</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container/src/VirtualFileSystem/binaryPack&quot;</span><span class="hl-1">;</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">buf</span><span class="hl-1"> = </span><span class="hl-0">encodeVfs</span><span class="hl-1">(</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-5">root</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">root</span><span class="hl-1"> = </span><span class="hl-0">decodeVfs</span><span class="hl-1">(</span><span class="hl-5">buf</span><span class="hl-1">);</span><br/><span class="hl-0">isBinarySnapshot</span><span class="hl-1">(</span><span class="hl-5">buf</span><span class="hl-1">); </span><span class="hl-3">// true — starts with &quot;VFS!&quot; magic</span>
531
+ </code><button type="button">Copy</button></pre>
532
+
533
+ <hr>
534
+ <h3 id="_-5" class="tsd-anchor-link"><code>VirtualUserManager</code><a href="#_-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
535
+ <p>Manages users, password hashing (scrypt), sudo privileges, storage quotas, SSH public keys, and session tracking.</p>
536
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualUserManager</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">: </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">autoSudoForNewUsers</span><span class="hl-1">?: </span><span class="hl-5">boolean</span><span class="hl-1">, </span><span class="hl-3">// default: true</span><br/><span class="hl-1">)</span>
537
+ </code><button type="button">Copy</button></pre>
538
+
539
+ <p>Auth data is stored at <code>/etc/</code> inside the VFS.</p>
540
+ <p><strong>Methods</strong></p>
541
+ <table>
542
+ <thead>
543
+ <tr>
544
+ <th>Method</th>
545
+ <th>Description</th>
546
+ </tr>
547
+ </thead>
548
+ <tbody>
549
+ <tr>
550
+ <td><code>initialize(): Promise&lt;void&gt;</code></td>
551
+ <td>Load users/sudoers, ensure root exists.</td>
552
+ </tr>
553
+ <tr>
554
+ <td><code>verifyPassword(username, password): boolean</code></td>
555
+ <td>Check plaintext password.</td>
556
+ </tr>
557
+ <tr>
558
+ <td><code>hasPassword(username): boolean</code></td>
559
+ <td>Returns <code>true</code> if a password is set.</td>
560
+ </tr>
561
+ <tr>
562
+ <td><code>hashPassword(password): string</code></td>
563
+ <td>Hash with scrypt (or SHA-256 with <code>SSH_MIMIC_FAST_PASSWORD_HASH=1</code>).</td>
564
+ </tr>
565
+ <tr>
566
+ <td><code>getPasswordHash(username): string | null</code></td>
567
+ <td>Raw stored hash.</td>
568
+ </tr>
569
+ <tr>
570
+ <td><code>addUser(username, password): Promise&lt;void&gt;</code></td>
571
+ <td>Create user with home directory.</td>
572
+ </tr>
573
+ <tr>
574
+ <td><code>deleteUser(username): Promise&lt;void&gt;</code></td>
575
+ <td>Delete user. Throws on <code>root</code> or missing user.</td>
576
+ </tr>
577
+ <tr>
578
+ <td><code>setPassword(username, password): Promise&lt;void&gt;</code></td>
579
+ <td>Update password.</td>
580
+ </tr>
581
+ <tr>
582
+ <td><code>isSudoer(username): boolean</code></td>
583
+ <td>Returns <code>true</code> if user has sudo.</td>
584
+ </tr>
585
+ <tr>
586
+ <td><code>addSudoer(username): Promise&lt;void&gt;</code></td>
587
+ <td>Grant sudo.</td>
588
+ </tr>
589
+ <tr>
590
+ <td><code>removeSudoer(username): Promise&lt;void&gt;</code></td>
591
+ <td>Revoke sudo. Throws on <code>root</code>.</td>
592
+ </tr>
593
+ <tr>
594
+ <td><code>setQuotaBytes(username, maxBytes): Promise&lt;void&gt;</code></td>
595
+ <td>Set per-user write quota.</td>
596
+ </tr>
597
+ <tr>
598
+ <td><code>clearQuota(username): Promise&lt;void&gt;</code></td>
599
+ <td>Remove quota limit.</td>
600
+ </tr>
601
+ <tr>
602
+ <td><code>getQuotaBytes(username): number | null</code></td>
603
+ <td>Quota in bytes, or <code>null</code> if unlimited.</td>
604
+ </tr>
605
+ <tr>
606
+ <td><code>getUsageBytes(username): number</code></td>
607
+ <td>Current usage under <code>/home/&lt;user&gt;</code>.</td>
608
+ </tr>
609
+ <tr>
610
+ <td><code>assertWriteWithinQuota(username, path, content)</code></td>
611
+ <td>Throws if write would exceed quota.</td>
612
+ </tr>
613
+ <tr>
614
+ <td><code>listUsers(): string[]</code></td>
615
+ <td>Sorted list of all usernames.</td>
616
+ </tr>
617
+ <tr>
618
+ <td><code>addAuthorizedKey(username, algo, data)</code></td>
619
+ <td>Register SSH public key.</td>
620
+ </tr>
621
+ <tr>
622
+ <td><code>getAuthorizedKeys(username)</code></td>
623
+ <td>List authorized keys.</td>
624
+ </tr>
625
+ <tr>
626
+ <td><code>removeAuthorizedKeys(username)</code></td>
627
+ <td>Revoke all authorized keys.</td>
628
+ </tr>
629
+ <tr>
630
+ <td><code>registerSession(username, remoteAddress): VirtualActiveSession</code></td>
631
+ <td>Allocate virtual TTY and register session.</td>
632
+ </tr>
633
+ <tr>
634
+ <td><code>unregisterSession(sessionId): void</code></td>
635
+ <td>Remove session on disconnect. Safe with <code>null</code>.</td>
636
+ </tr>
637
+ <tr>
638
+ <td><code>updateSession(sessionId, username, remoteAddress): void</code></td>
639
+ <td>Update after <code>su</code>/<code>sudo</code> identity change.</td>
640
+ </tr>
641
+ <tr>
642
+ <td><code>listActiveSessions(): VirtualActiveSession[]</code></td>
643
+ <td>All active sessions sorted by start time.</td>
644
+ </tr>
645
+ </tbody>
646
+ </table>
647
+ <p><strong>Events:</strong> <code>initialized</code>, <code>user:add { username }</code>, <code>user:delete { username }</code>, <code>key:add { username, algo }</code>, <code>key:remove { username }</code>, <code>session:register { sessionId, username, remoteAddress }</code>, <code>session:unregister { sessionId, username }</code></p>
648
+ <hr>
649
+ <h3 id="_-6" class="tsd-anchor-link"><code>VirtualPackageManager</code><a href="#_-6" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
650
+ <p>Simulates APT/dpkg backed by a 25-package registry. Accessed via <code>shell.packageManager</code>.</p>
651
+ <p><strong>Methods</strong></p>
652
+ <table>
653
+ <thead>
654
+ <tr>
655
+ <th>Method</th>
656
+ <th>Description</th>
657
+ </tr>
658
+ </thead>
659
+ <tbody>
660
+ <tr>
661
+ <td><code>install(names, opts?)</code></td>
662
+ <td>Install packages (resolves deps, writes files to VFS). Returns <code>{ output, exitCode }</code></td>
663
+ </tr>
664
+ <tr>
665
+ <td><code>remove(names, opts?)</code></td>
666
+ <td>Remove. <code>opts.purge</code> also removes config files.</td>
667
+ </tr>
668
+ <tr>
669
+ <td><code>search(term)</code></td>
670
+ <td>Search by name or description.</td>
671
+ </tr>
672
+ <tr>
673
+ <td><code>show(name)</code></td>
674
+ <td>dpkg-style metadata block.</td>
675
+ </tr>
676
+ <tr>
677
+ <td><code>listInstalled()</code></td>
678
+ <td>All installed packages as <code>InstalledPackage[]</code>.</td>
679
+ </tr>
680
+ <tr>
681
+ <td><code>listAvailable()</code></td>
682
+ <td>All registry packages.</td>
683
+ </tr>
684
+ <tr>
685
+ <td><code>isInstalled(name)</code></td>
686
+ <td>Returns <code>true</code> if installed.</td>
687
+ </tr>
688
+ <tr>
689
+ <td><code>installedCount()</code></td>
690
+ <td>Count of installed packages.</td>
691
+ </tr>
692
+ <tr>
693
+ <td><code>findInRegistry(name)</code></td>
694
+ <td>Look up <code>PackageDefinition</code> by name.</td>
695
+ </tr>
696
+ </tbody>
697
+ </table>
698
+ <p><strong>Custom packages:</strong></p>
699
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">customPkg</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-5">name:</span><span class="hl-1"> </span><span class="hl-2">&quot;myapp&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">version:</span><span class="hl-1"> </span><span class="hl-2">&quot;1.0.0&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">description:</span><span class="hl-1"> </span><span class="hl-2">&quot;My application&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">files:</span><span class="hl-1"> [</span><br/><span class="hl-1"> { </span><span class="hl-5">path:</span><span class="hl-1"> </span><span class="hl-2">&quot;/usr/bin/myapp&quot;</span><span class="hl-1">, </span><span class="hl-5">content:</span><span class="hl-1"> </span><span class="hl-2">&quot;#!/bin/sh</span><span class="hl-18">\n</span><span class="hl-2">echo myapp v1.0.0</span><span class="hl-18">\n</span><span class="hl-2">&quot;</span><span class="hl-1">, </span><span class="hl-5">mode:</span><span class="hl-1"> </span><span class="hl-8">0o755</span><span class="hl-1"> },</span><br/><span class="hl-1"> { </span><span class="hl-5">path:</span><span class="hl-1"> </span><span class="hl-2">&quot;/etc/myapp/config.json&quot;</span><span class="hl-1">, </span><span class="hl-5">content:</span><span class="hl-1"> </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">stringify</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">3000</span><span class="hl-1"> }) },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> </span><span class="hl-0">onInstall</span><span class="hl-5">:</span><span class="hl-1"> (</span><span class="hl-5">vfs</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">mkdir</span><span class="hl-1">(</span><span class="hl-2">&quot;/var/lib/myapp&quot;</span><span class="hl-1">, </span><span class="hl-8">0o755</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">mkdir</span><span class="hl-1">(</span><span class="hl-2">&quot;/var/log/myapp&quot;</span><span class="hl-1">, </span><span class="hl-8">0o755</span><span class="hl-1">);</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">};</span>
700
+ </code><button type="button">Copy</button></pre>
701
+
702
+ <hr>
703
+ <h3 id="snapshot-diff-tooling" class="tsd-anchor-link">Snapshot Diff Tooling<a href="#snapshot-diff-tooling" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
704
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">diffSnapshots</span><span class="hl-1">, </span><span class="hl-5">formatDiff</span><span class="hl-1">, </span><span class="hl-5">assertDiff</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span>
705
+ </code><button type="button">Copy</button></pre>
706
+
707
+ <p><strong><code>diffSnapshots(before, after, options?): VfsDiff</code></strong></p>
708
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">before</span><span class="hl-1"> = </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">();</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;apt install vim &amp;&amp; mkdir -p /app&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">after</span><span class="hl-1"> = </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">();</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">diff</span><span class="hl-1"> = </span><span class="hl-0">diffSnapshots</span><span class="hl-1">(</span><span class="hl-5">before</span><span class="hl-1">, </span><span class="hl-5">after</span><span class="hl-1">, { </span><span class="hl-5">ignore:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/proc&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;/var/log&quot;</span><span class="hl-1">] });</span><br/><span class="hl-5">diff</span><span class="hl-1">.</span><span class="hl-5">clean</span><span class="hl-1">; </span><span class="hl-3">// false</span><br/><span class="hl-5">diff</span><span class="hl-1">.</span><span class="hl-5">added</span><span class="hl-1">; </span><span class="hl-3">// [{ path: &quot;/usr/bin/vim&quot;, type: &quot;file&quot; }, ...]</span><br/><span class="hl-5">diff</span><span class="hl-1">.</span><span class="hl-5">modified</span><span class="hl-1">; </span><span class="hl-3">// [{ path: &quot;/var/lib/dpkg/status&quot;, before: &quot;...&quot;, after: &quot;...&quot; }]</span>
709
+ </code><button type="button">Copy</button></pre>
710
+
711
+ <p><strong><code>formatDiff(diff, options?): string</code></strong> — human-readable output like <code>git diff --stat</code>. Options: <code>showContent: boolean</code>, <code>maxContentChars: number</code>.</p>
712
+ <p><strong><code>assertDiff(diff, expected): void</code></strong> — throws on mismatch, designed for test suites:</p>
713
+ <pre><code class="typescript"><span class="hl-0">assertDiff</span><span class="hl-1">(</span><span class="hl-5">diff</span><span class="hl-1">, { </span><span class="hl-5">added:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/app&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;/usr/bin/vim&quot;</span><span class="hl-1">], </span><span class="hl-5">modified:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/var/lib/dpkg/status&quot;</span><span class="hl-1">] });</span>
714
+ </code><button type="button">Copy</button></pre>
715
+
716
+ <hr>
717
+ <h3 id="_-7" class="tsd-anchor-link"><code>HoneyPot</code><a href="#_-7" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
718
+ <p>Comprehensive security auditing. Attaches to all core components to log activity and detect anomalies.</p>
719
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">HoneyPot</span><span class="hl-1">(</span><span class="hl-5">maxLogSize</span><span class="hl-1">?: </span><span class="hl-5">number</span><span class="hl-1">) </span><span class="hl-3">// default: 10000</span>
720
+ </code><button type="button">Copy</button></pre>
721
+
722
+ <p><strong>Methods</strong></p>
723
+ <table>
724
+ <thead>
725
+ <tr>
726
+ <th>Method</th>
727
+ <th>Description</th>
728
+ </tr>
729
+ </thead>
730
+ <tbody>
731
+ <tr>
732
+ <td><code>attach(shell, vfs, users, ssh?, sftp?)</code></td>
733
+ <td>Subscribe to all event sources.</td>
734
+ </tr>
735
+ <tr>
736
+ <td><code>getAuditLog(type?, source?): AuditLogEntry[]</code></td>
737
+ <td>Full log, optionally filtered.</td>
738
+ </tr>
739
+ <tr>
740
+ <td><code>getStats(): Readonly&lt;HoneyPotStats&gt;</code></td>
741
+ <td>Aggregated activity counters.</td>
742
+ </tr>
743
+ <tr>
744
+ <td><code>getRecent(limit?): AuditLogEntry[]</code></td>
745
+ <td>Most recent entries, reverse-chronological.</td>
746
+ </tr>
747
+ <tr>
748
+ <td><code>detectAnomalies()</code></td>
749
+ <td>Returns <code>{ type, severity, message }[]</code>.</td>
750
+ </tr>
751
+ <tr>
752
+ <td><code>reset()</code></td>
753
+ <td>Clear log and reset counters.</td>
754
+ </tr>
755
+ <tr>
756
+ <td><code>exportJson(): string</code></td>
757
+ <td>Serialise full log + stats to JSON.</td>
758
+ </tr>
759
+ </tbody>
760
+ </table>
761
+ <p><code>detectAnomalies</code> detects: high auth failure rates, excessive failures, unusual command volume, unusual file write volume.</p>
762
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">hp</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">HoneyPot</span><span class="hl-1">(</span><span class="hl-8">50_000</span><span class="hl-1">);</span><br/><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">attach</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">users</span><span class="hl-1">, </span><span class="hl-5">ssh</span><span class="hl-1">);</span><br/><br/><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">getAuditLog</span><span class="hl-1">(</span><span class="hl-2">&quot;auth:failure&quot;</span><span class="hl-1">).</span><span class="hl-0">forEach</span><span class="hl-1">(</span><span class="hl-5">e</span><span class="hl-1"> </span><span class="hl-4">=&gt;</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">e</span><span class="hl-1">.</span><span class="hl-5">details</span><span class="hl-1">.</span><span class="hl-5">username</span><span class="hl-1">, </span><span class="hl-5">e</span><span class="hl-1">.</span><span class="hl-5">details</span><span class="hl-1">.</span><span class="hl-5">remoteAddress</span><span class="hl-1">)</span><br/><span class="hl-1">);</span><br/><br/><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">detectAnomalies</span><span class="hl-1">().</span><span class="hl-0">forEach</span><span class="hl-1">(</span><span class="hl-5">a</span><span class="hl-1"> </span><span class="hl-4">=&gt;</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">severity</span><span class="hl-11">.</span><span class="hl-0">toUpperCase</span><span class="hl-11">()</span><span class="hl-4">}</span><span class="hl-2">] </span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">type</span><span class="hl-4">}</span><span class="hl-2">: </span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">)</span><br/><span class="hl-1">);</span><br/><br/><span class="hl-5">process</span><span class="hl-1">.</span><span class="hl-0">on</span><span class="hl-1">(</span><span class="hl-2">&quot;SIGINT&quot;</span><span class="hl-1">, () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">require</span><span class="hl-1">(</span><span class="hl-2">&quot;fs&quot;</span><span class="hl-1">).</span><span class="hl-0">writeFileSync</span><span class="hl-1">(</span><span class="hl-2">&quot;audit.json&quot;</span><span class="hl-1">, </span><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">exportJson</span><span class="hl-1">());</span><br/><span class="hl-1"> </span><span class="hl-5">process</span><span class="hl-1">.</span><span class="hl-0">exit</span><span class="hl-1">(</span><span class="hl-8">0</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
763
+ </code><button type="button">Copy</button></pre>
764
+
765
+ <hr>
766
+ <h3 id="programmatic-api-1" class="tsd-anchor-link"><code>SshClient</code> (Programmatic API)<a href="#programmatic-api-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
767
+ <p>Execute shell commands against a <code>VirtualShell</code> without SSH overhead. Maintains working-directory state.</p>
768
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">: </span><span class="hl-5">VirtualShell</span><span class="hl-1">, </span><span class="hl-5">username</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">)</span>
769
+ </code><button type="button">Copy</button></pre>
770
+
771
+ <p><strong>Methods</strong></p>
772
+ <table>
773
+ <thead>
774
+ <tr>
775
+ <th>Method</th>
776
+ <th>Description</th>
777
+ </tr>
778
+ </thead>
779
+ <tbody>
780
+ <tr>
781
+ <td><code>exec(command): Promise&lt;CommandResult&gt;</code></td>
782
+ <td>Run raw command string (supports <code>&amp;&amp;</code>, <code>|</code>, etc.).</td>
783
+ </tr>
784
+ <tr>
785
+ <td><code>ls(path?)</code></td>
786
+ <td>List directory.</td>
787
+ </tr>
788
+ <tr>
789
+ <td><code>pwd()</code></td>
790
+ <td>Print current working directory.</td>
791
+ </tr>
792
+ <tr>
793
+ <td><code>cd(path)</code></td>
794
+ <td>Change directory. Updates internal cwd on success.</td>
795
+ </tr>
796
+ <tr>
797
+ <td><code>cat(path)</code></td>
798
+ <td>Read file via <code>cat</code> command.</td>
799
+ </tr>
800
+ <tr>
801
+ <td><code>readFile(path)</code></td>
802
+ <td>Read file directly from VFS.</td>
803
+ </tr>
804
+ <tr>
805
+ <td><code>writeFile(path, content)</code></td>
806
+ <td>Write file directly to VFS.</td>
807
+ </tr>
808
+ <tr>
809
+ <td><code>mkdir(path, recursive?)</code></td>
810
+ <td>Create directory.</td>
811
+ </tr>
812
+ <tr>
813
+ <td><code>touch(path)</code></td>
814
+ <td>Create empty file.</td>
815
+ </tr>
816
+ <tr>
817
+ <td><code>rm(path, recursive?)</code></td>
818
+ <td>Remove file or directory.</td>
819
+ </tr>
820
+ <tr>
821
+ <td><code>tree(path?)</code></td>
822
+ <td>Render ASCII directory tree.</td>
823
+ </tr>
824
+ <tr>
825
+ <td><code>whoami()</code> / <code>hostname()</code> / <code>who()</code></td>
826
+ <td>System info commands.</td>
827
+ </tr>
828
+ <tr>
829
+ <td><code>getCwd(): string</code></td>
830
+ <td>Returns current cwd (no I/O).</td>
831
+ </tr>
832
+ <tr>
833
+ <td><code>getUsername(): string</code></td>
834
+ <td>Returns authenticated username.</td>
835
+ </tr>
836
+ </tbody>
837
+ </table>
838
+ <hr>
839
+ <h3 id="key-types" class="tsd-anchor-link">Key Types<a href="#key-types" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
840
+ <pre><code class="typescript"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">CommandResult</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">stdout</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">stderr</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">exitCode</span><span class="hl-1">?: </span><span class="hl-17">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">nextCwd</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">clearScreen</span><span class="hl-1">?: </span><span class="hl-17">boolean</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">closeSession</span><span class="hl-1">?: </span><span class="hl-17">boolean</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">switchUser</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">openEditor</span><span class="hl-1">?: </span><span class="hl-17">NanoEditorSession</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">openHtop</span><span class="hl-1">?: </span><span class="hl-17">boolean</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">sudoChallenge</span><span class="hl-1">?: </span><span class="hl-17">SudoChallenge</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">ShellEnv</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">vars</span><span class="hl-1">: </span><span class="hl-17">Record</span><span class="hl-1">&lt;</span><span class="hl-17">string</span><span class="hl-1">, </span><span class="hl-17">string</span><span class="hl-1">&gt;; </span><span class="hl-3">// $VAR accessible in expansions</span><br/><span class="hl-1"> </span><span class="hl-5">lastExitCode</span><span class="hl-1">: </span><span class="hl-17">number</span><span class="hl-1">; </span><span class="hl-3">// $?</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">ShellModule</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">name</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">params</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">[];</span><br/><span class="hl-1"> </span><span class="hl-5">aliases</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">[];</span><br/><span class="hl-1"> </span><span class="hl-5">description</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">category</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// navigation|files|text|archive|system|package|network|shell|users|misc</span><br/><span class="hl-1"> </span><span class="hl-0">run</span><span class="hl-1">: (</span><span class="hl-5">ctx</span><span class="hl-1">: </span><span class="hl-17">CommandContext</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-17">CommandResult</span><span class="hl-1"> | </span><span class="hl-17">Promise</span><span class="hl-1">&lt;</span><span class="hl-17">CommandResult</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">CommandContext</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">authUser</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">hostname</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">activeSessions</span><span class="hl-1">: </span><span class="hl-17">VirtualActiveSession</span><span class="hl-1">[];</span><br/><span class="hl-1"> </span><span class="hl-5">rawInput</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">mode</span><span class="hl-1">: </span><span class="hl-2">&quot;shell&quot;</span><span class="hl-1"> | </span><span class="hl-2">&quot;exec&quot;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">args</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">[];</span><br/><span class="hl-1"> </span><span class="hl-5">stdin</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">cwd</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">: </span><span class="hl-17">VirtualShell</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">env</span><span class="hl-1">: </span><span class="hl-17">ShellEnv</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">VirtualActiveSession</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">id</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">username</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">tty</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">remoteAddress</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">startedAt</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// ISO-8601</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-3">/** Returned by adduser, passwd, deluser — triggers interactive password prompt in the terminal. */</span><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-17">PasswordChallenge</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">preamble</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// Lines printed before the first prompt</span><br/><span class="hl-1"> </span><span class="hl-5">prompt</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// e.g. &quot;New password: &quot;</span><br/><span class="hl-1"> </span><span class="hl-5">confirmPrompt</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// Second prompt for confirmation</span><br/><span class="hl-1"> </span><span class="hl-5">confirmText</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// Destructive confirmation prompt (y/N)</span><br/><span class="hl-1"> </span><span class="hl-5">action</span><span class="hl-1">: </span><span class="hl-2">&quot;adduser&quot;</span><span class="hl-1"> | </span><span class="hl-2">&quot;passwd&quot;</span><span class="hl-1"> | </span><span class="hl-2">&quot;deluser&quot;</span><span class="hl-1"> | </span><span class="hl-2">&quot;su&quot;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">targetUsername</span><span class="hl-1">: </span><span class="hl-17">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-5">newUsername</span><span class="hl-1">?: </span><span class="hl-17">string</span><span class="hl-1">; </span><span class="hl-3">// adduser only</span><br/><span class="hl-1">}</span>
841
+ </code><button type="button">Copy</button></pre>
842
+
843
+ <hr>
844
+ <h3 id="command-helpers" class="tsd-anchor-link">Command Helpers<a href="#command-helpers" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
845
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">ifFlag</span><span class="hl-1">, </span><span class="hl-5">getFlag</span><span class="hl-1">, </span><span class="hl-5">getArg</span><span class="hl-1">, </span><span class="hl-5">parseArgs</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// ifFlag — true if any given flag appears in args</span><br/><span class="hl-0">ifFlag</span><span class="hl-1">(</span><span class="hl-5">args</span><span class="hl-1">, [</span><span class="hl-2">&quot;-r&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;--recursive&quot;</span><span class="hl-1">]) </span><span class="hl-3">// boolean</span><br/><br/><span class="hl-3">// getFlag — value, true if valueless, undefined if absent</span><br/><span class="hl-0">getFlag</span><span class="hl-1">(</span><span class="hl-5">args</span><span class="hl-1">, [</span><span class="hl-2">&quot;-o&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;--output&quot;</span><span class="hl-1">])</span><br/><span class="hl-3">// [&quot;--output&quot;, &quot;file.txt&quot;] → &quot;file.txt&quot;</span><br/><span class="hl-3">// [&quot;--output=file.txt&quot;] → &quot;file.txt&quot;</span><br/><span class="hl-3">// [&quot;--verbose&quot;] → true</span><br/><span class="hl-3">// [] → undefined</span><br/><br/><span class="hl-3">// getArg — positional at index N, skipping known flags</span><br/><span class="hl-3">// args = [&quot;-r&quot;, &quot;src&quot;, &quot;dest&quot;]</span><br/><span class="hl-0">getArg</span><span class="hl-1">(</span><span class="hl-5">args</span><span class="hl-1">, </span><span class="hl-8">0</span><span class="hl-1">, { </span><span class="hl-5">flags:</span><span class="hl-1"> [</span><span class="hl-2">&quot;-r&quot;</span><span class="hl-1">] }) </span><span class="hl-3">// &quot;src&quot;</span><br/><span class="hl-0">getArg</span><span class="hl-1">(</span><span class="hl-5">args</span><span class="hl-1">, </span><span class="hl-8">1</span><span class="hl-1">, { </span><span class="hl-5">flags:</span><span class="hl-1"> [</span><span class="hl-2">&quot;-r&quot;</span><span class="hl-1">] }) </span><span class="hl-3">// &quot;dest&quot;</span><br/><br/><span class="hl-3">// parseArgs — structured parse</span><br/><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-7">flags</span><span class="hl-1">, </span><span class="hl-7">flagsWithValues</span><span class="hl-1">, </span><span class="hl-7">positionals</span><span class="hl-1"> } = </span><span class="hl-0">parseArgs</span><span class="hl-1">(</span><span class="hl-5">args</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-5">flags:</span><span class="hl-1"> [</span><span class="hl-2">&quot;-r&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;--recursive&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-5">flagsWithValue:</span><span class="hl-1"> [</span><span class="hl-2">&quot;-o&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;--output&quot;</span><span class="hl-1">],</span><br/><span class="hl-1">});</span>
846
+ </code><button type="button">Copy</button></pre>
847
+
848
+ </details>
849
+ <hr>
850
+ <details>
851
+ <summary><strong>Examples</strong></summary>
852
+ <h3 id="ssh-server-with-events" class="tsd-anchor-link">SSH Server with Events<a href="#ssh-server-with-events" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
853
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">VirtualSshServer</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">hostname:</span><span class="hl-1"> </span><span class="hl-2">&quot;lab-environment&quot;</span><span class="hl-1"> });</span><br/><br/><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">on</span><span class="hl-1">(</span><span class="hl-2">&quot;auth:success&quot;</span><span class="hl-1">, ({ </span><span class="hl-5">username</span><span class="hl-1">, </span><span class="hl-5">remoteAddress</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[SSH] </span><span class="hl-4">${</span><span class="hl-5">username</span><span class="hl-4">}</span><span class="hl-2"> from </span><span class="hl-4">${</span><span class="hl-5">remoteAddress</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1">});</span><br/><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">on</span><span class="hl-1">(</span><span class="hl-2">&quot;auth:lockout&quot;</span><span class="hl-1">, ({ </span><span class="hl-5">ip</span><span class="hl-1">, </span><span class="hl-5">until</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">warn</span><span class="hl-1">(</span><span class="hl-2">`[SSH] </span><span class="hl-4">${</span><span class="hl-5">ip</span><span class="hl-4">}</span><span class="hl-2"> locked until </span><span class="hl-4">${</span><span class="hl-5">until</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><span class="hl-5">process</span><span class="hl-1">.</span><span class="hl-0">on</span><span class="hl-1">(</span><span class="hl-2">&quot;SIGINT&quot;</span><span class="hl-1">, () </span><span class="hl-4">=&gt;</span><span class="hl-1"> { </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">stop</span><span class="hl-1">(); </span><span class="hl-5">process</span><span class="hl-1">.</span><span class="hl-0">exit</span><span class="hl-1">(</span><span class="hl-8">0</span><span class="hl-1">); });</span>
854
+ </code><button type="button">Copy</button></pre>
855
+
856
+ <h3 id="ssh-sftp-with-shared-state" class="tsd-anchor-link">SSH + SFTP with Shared State<a href="#ssh-sftp-with-shared-state" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
857
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">VirtualSftpServer</span><span class="hl-1">, </span><span class="hl-5">VirtualShell</span><span class="hl-1">, </span><span class="hl-5">VirtualSshServer</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;my-container&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">sftp</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSftpServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2223</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">sftp</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span>
858
+ </code><button type="button">Copy</button></pre>
859
+
860
+ <h3 id="multi-user-environment-with-quotas" class="tsd-anchor-link">Multi-User Environment with Quotas<a href="#multi-user-environment-with-quotas" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
861
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">SshClient</span><span class="hl-1">, </span><span class="hl-5">VirtualShell</span><span class="hl-1">, </span><span class="hl-5">VirtualSshServer</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;typescript-vm&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">users</span><span class="hl-1"> = </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">getUsers</span><span class="hl-1">()!;</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">addUser</span><span class="hl-1">(</span><span class="hl-2">&quot;alice&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;alice123&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">addUser</span><span class="hl-1">(</span><span class="hl-2">&quot;bob&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;bob456&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">removeSudoer</span><span class="hl-1">(</span><span class="hl-2">&quot;bob&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">setQuotaBytes</span><span class="hl-1">(</span><span class="hl-2">&quot;bob&quot;</span><span class="hl-1">, </span><span class="hl-8">5</span><span class="hl-1"> * </span><span class="hl-8">1024</span><span class="hl-1"> * </span><span class="hl-8">1024</span><span class="hl-1">); </span><span class="hl-3">// 5 MB</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">alice</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;alice&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">alice</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/etc/important.conf&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;secret=yes&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">bob</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;bob&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">r</span><span class="hl-1"> = </span><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">bob</span><span class="hl-1">.</span><span class="hl-0">cat</span><span class="hl-1">(</span><span class="hl-2">&quot;/etc/important.conf&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">r</span><span class="hl-1">.</span><span class="hl-5">stderr</span><span class="hl-1">); </span><span class="hl-3">// permission denied</span>
862
+ </code><button type="button">Copy</button></pre>
863
+
864
+ <h3 id="persistent-state" class="tsd-anchor-link">Persistent State<a href="#persistent-state" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
865
+ <pre><code class="typescript"><span class="hl-3">// FS mode — automatic .vfsb persistence</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;my-vm&quot;</span><span class="hl-1">, </span><span class="hl-4">undefined</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-5">mode:</span><span class="hl-1"> </span><span class="hl-2">&quot;fs&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">snapshotPath:</span><span class="hl-1"> </span><span class="hl-2">&quot;./container-data&quot;</span><span class="hl-1">,</span><br/><span class="hl-1">});</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><span class="hl-3">// Restored from ./container-data/vfs-snapshot.vfsb on start, saved on every write.</span><br/><br/><span class="hl-3">// Memory mode — manual JSON snapshot</span><br/><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">writeFileSync</span><span class="hl-1">, </span><span class="hl-5">readFileSync</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;node:fs&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">vfs</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualFileSystem</span><span class="hl-1">();</span><br/><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/data/report.txt&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;Baseline data&quot;</span><span class="hl-1">);</span><br/><span class="hl-0">writeFileSync</span><span class="hl-1">(</span><span class="hl-2">&quot;snapshot.json&quot;</span><span class="hl-1">, </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">stringify</span><span class="hl-1">(</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">()));</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">restored</span><span class="hl-1"> = </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1">.</span><span class="hl-0">fromSnapshot</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">parse</span><span class="hl-1">(</span><span class="hl-0">readFileSync</span><span class="hl-1">(</span><span class="hl-2">&quot;snapshot.json&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;utf8&quot;</span><span class="hl-1">))</span><br/><span class="hl-1">);</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">restored</span><span class="hl-1">.</span><span class="hl-0">readFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/data/report.txt&quot;</span><span class="hl-1">)); </span><span class="hl-3">// Baseline data</span>
866
+ </code><button type="button">Copy</button></pre>
867
+
868
+ <h3 id="public-key-authentication" class="tsd-anchor-link">Public-Key Authentication<a href="#public-key-authentication" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
869
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">readFileSync</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;node:fs&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;secure-vm&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">ensureInitialized</span><span class="hl-1">();</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">addUser</span><span class="hl-1">(</span><span class="hl-2">&quot;alice&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;fallback-password&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">pubLine</span><span class="hl-1"> = </span><span class="hl-0">readFileSync</span><span class="hl-1">(</span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">process</span><span class="hl-11">.</span><span class="hl-5">env</span><span class="hl-11">.</span><span class="hl-7">HOME</span><span class="hl-4">}</span><span class="hl-2">/.ssh/id_ed25519.pub`</span><span class="hl-1">, </span><span class="hl-2">&quot;utf8&quot;</span><span class="hl-1">).</span><span class="hl-0">trim</span><span class="hl-1">();</span><br/><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-7">algo</span><span class="hl-1">, </span><span class="hl-7">b64</span><span class="hl-1">] = </span><span class="hl-5">pubLine</span><span class="hl-1">.</span><span class="hl-0">split</span><span class="hl-1">(</span><span class="hl-2">&quot; &quot;</span><span class="hl-1">);</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">users</span><span class="hl-1">.</span><span class="hl-0">addAuthorizedKey</span><span class="hl-1">(</span><span class="hl-2">&quot;alice&quot;</span><span class="hl-1">, </span><span class="hl-5">algo</span><span class="hl-1">, </span><span class="hl-5">Buffer</span><span class="hl-1">.</span><span class="hl-0">from</span><span class="hl-1">(</span><span class="hl-5">b64</span><span class="hl-1">, </span><span class="hl-2">&quot;base64&quot;</span><span class="hl-1">));</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><span class="hl-3">// ssh -i ~/.ssh/id_ed25519 alice@localhost -p 2222</span>
870
+ </code><button type="button">Copy</button></pre>
871
+
872
+ <h3 id="rate-limiting" class="tsd-anchor-link">Rate Limiting<a href="#rate-limiting" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
873
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">maxAuthAttempts:</span><span class="hl-1"> </span><span class="hl-8">3</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">lockoutDurationMs:</span><span class="hl-1"> </span><span class="hl-8">300_000</span><span class="hl-1">,</span><br/><span class="hl-1">});</span><br/><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">on</span><span class="hl-1">(</span><span class="hl-2">&quot;auth:lockout&quot;</span><span class="hl-1">, ({ </span><span class="hl-5">ip</span><span class="hl-1">, </span><span class="hl-5">until</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">warn</span><span class="hl-1">(</span><span class="hl-2">`</span><span class="hl-4">${</span><span class="hl-5">ip</span><span class="hl-4">}</span><span class="hl-2"> locked until </span><span class="hl-4">${</span><span class="hl-5">until</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">));</span><br/><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">clearLockout</span><span class="hl-1">(</span><span class="hl-2">&quot;192.168.1.100&quot;</span><span class="hl-1">); </span><span class="hl-3">// manual override</span>
874
+ </code><button type="button">Copy</button></pre>
875
+
876
+ <h3 id="shell-operators-and-variables" class="tsd-anchor-link">Shell Operators and Variables<a href="#shell-operators-and-variables" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
877
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">client</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;root&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;mkdir /tmp/test &amp;&amp; echo created || echo failed&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;export GREETING=hello &amp;&amp; echo $GREETING world&quot;</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;false; echo exit=$?&quot;</span><span class="hl-1">); </span><span class="hl-3">// exit=1</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">r</span><span class="hl-1"> = </span><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;echo -e &#39;banana</span><span class="hl-18">\\</span><span class="hl-2">napple</span><span class="hl-18">\\</span><span class="hl-2">ncherry&#39; | sort&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">r</span><span class="hl-1">.</span><span class="hl-5">stdout</span><span class="hl-1">); </span><span class="hl-3">// apple\nbanana\ncherry</span>
878
+ </code><button type="button">Copy</button></pre>
879
+
880
+ <h3 id="shell-scripting" class="tsd-anchor-link">Shell Scripting<a href="#shell-scripting" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
881
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/usr/local/bin/setup.sh&quot;</span><span class="hl-1">, </span><span class="hl-2">`</span><br/><span class="hl-2">#!/bin/sh</span><br/><span class="hl-2">for dir in config logs tmp; do</span><br/><span class="hl-2"> mkdir /app/$dir</span><br/><span class="hl-2"> echo &quot;Created /app/$dir&quot;</span><br/><span class="hl-2">done</span><br/><span class="hl-2">if [ -d /app/config ]; then</span><br/><span class="hl-2"> echo &quot;Setup complete&quot;</span><br/><span class="hl-2">fi</span><br/><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">r</span><span class="hl-1"> = </span><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;sh /usr/local/bin/setup.sh&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">r</span><span class="hl-1">.</span><span class="hl-5">stdout</span><span class="hl-1">);</span>
882
+ </code><button type="button">Copy</button></pre>
883
+
884
+ <h3 id="snapshot-based-test-fixtures" class="tsd-anchor-link">Snapshot-Based Test Fixtures<a href="#snapshot-based-test-fixtures" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
885
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><span class="hl-6">import</span><span class="hl-1"> </span><span class="hl-6">type</span><span class="hl-1"> { </span><span class="hl-5">VfsSnapshot</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-0">buildFixture</span><span class="hl-1">(): </span><span class="hl-17">VfsSnapshot</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">vfs</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualFileSystem</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">mkdir</span><span class="hl-1">(</span><span class="hl-2">&quot;/app/config&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/app/config/settings.json&quot;</span><span class="hl-1">, </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">stringify</span><span class="hl-1">({ </span><span class="hl-5">env:</span><span class="hl-1"> </span><span class="hl-2">&quot;test&quot;</span><span class="hl-1"> }));</span><br/><span class="hl-1"> </span><span class="hl-6">return</span><span class="hl-1"> </span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">();</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">FIXTURE</span><span class="hl-1"> = </span><span class="hl-0">buildFixture</span><span class="hl-1">();</span><br/><br/><span class="hl-0">test</span><span class="hl-1">(</span><span class="hl-2">&quot;reads config file&quot;</span><span class="hl-1">, () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">vfs</span><span class="hl-1"> = </span><span class="hl-5">VirtualFileSystem</span><span class="hl-1">.</span><span class="hl-0">fromSnapshot</span><span class="hl-1">(</span><span class="hl-7">FIXTURE</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">content</span><span class="hl-1"> = </span><span class="hl-7">JSON</span><span class="hl-1">.</span><span class="hl-0">parse</span><span class="hl-1">(</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">readFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/app/config/settings.json&quot;</span><span class="hl-1">));</span><br/><span class="hl-1"> </span><span class="hl-0">expect</span><span class="hl-1">(</span><span class="hl-5">content</span><span class="hl-1">.</span><span class="hl-5">env</span><span class="hl-1">).</span><span class="hl-0">toBe</span><span class="hl-1">(</span><span class="hl-2">&quot;test&quot;</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
886
+ </code><button type="button">Copy</button></pre>
887
+
888
+ <h3 id="snapshot-diff-in-tests" class="tsd-anchor-link">Snapshot Diff in Tests<a href="#snapshot-diff-in-tests" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
889
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">diffSnapshots</span><span class="hl-1">, </span><span class="hl-5">assertDiff</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">before</span><span class="hl-1"> = </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">();</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;apt install vim &amp;&amp; mkdir -p /app&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">after</span><span class="hl-1"> = </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">toSnapshot</span><span class="hl-1">();</span><br/><br/><span class="hl-0">assertDiff</span><span class="hl-1">(</span><span class="hl-0">diffSnapshots</span><span class="hl-1">(</span><span class="hl-5">before</span><span class="hl-1">, </span><span class="hl-5">after</span><span class="hl-1">, { </span><span class="hl-5">ignore:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/proc&quot;</span><span class="hl-1">] }), {</span><br/><span class="hl-1"> </span><span class="hl-5">added:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/app&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;/usr/bin/vim&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-5">modified:</span><span class="hl-1"> [</span><span class="hl-2">&quot;/var/lib/dpkg/status&quot;</span><span class="hl-1">],</span><br/><span class="hl-1">});</span>
890
+ </code><button type="button">Copy</button></pre>
891
+
892
+ <h3 id="symlinks" class="tsd-anchor-link">Symlinks<a href="#symlinks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
893
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">vfs</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualFileSystem</span><span class="hl-1">();</span><br/><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/opt/myapp/bin/app&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;#!/bin/sh</span><span class="hl-18">\n</span><span class="hl-2">echo hello&quot;</span><span class="hl-1">);</span><br/><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">symlink</span><span class="hl-1">(</span><span class="hl-2">&quot;/opt/myapp/bin/app&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;/usr/local/bin/app&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">isSymlink</span><span class="hl-1">(</span><span class="hl-2">&quot;/usr/local/bin/app&quot;</span><span class="hl-1">)); </span><span class="hl-3">// true</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">resolveSymlink</span><span class="hl-1">(</span><span class="hl-2">&quot;/usr/local/bin/app&quot;</span><span class="hl-1">)); </span><span class="hl-3">// /opt/myapp/bin/app</span>
894
+ </code><button type="button">Copy</button></pre>
895
+
896
+ <h3 id="security-auditing-with-honeypot" class="tsd-anchor-link">Security Auditing with HoneyPot<a href="#security-auditing-with-honeypot" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
897
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> { </span><span class="hl-5">HoneyPot</span><span class="hl-1">, </span><span class="hl-5">VirtualShell</span><span class="hl-1">, </span><span class="hl-5">VirtualSshServer</span><span class="hl-1"> } </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;typescript-vm&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">ssh</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({ </span><span class="hl-5">port:</span><span class="hl-1"> </span><span class="hl-8">2222</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1"> });</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">ssh</span><span class="hl-1">.</span><span class="hl-0">start</span><span class="hl-1">();</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">hp</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">HoneyPot</span><span class="hl-1">(</span><span class="hl-8">5000</span><span class="hl-1">);</span><br/><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">attach</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">, </span><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">users</span><span class="hl-1">, </span><span class="hl-5">ssh</span><span class="hl-1">);</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">stats</span><span class="hl-1"> = </span><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">getStats</span><span class="hl-1">();</span><br/><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`Commands: </span><span class="hl-4">${</span><span class="hl-5">stats</span><span class="hl-11">.</span><span class="hl-5">commands</span><span class="hl-4">}</span><span class="hl-2">, File writes: </span><span class="hl-4">${</span><span class="hl-5">stats</span><span class="hl-11">.</span><span class="hl-5">fileWrites</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">);</span><br/><br/><span class="hl-5">hp</span><span class="hl-1">.</span><span class="hl-0">detectAnomalies</span><span class="hl-1">().</span><span class="hl-0">forEach</span><span class="hl-1">(</span><span class="hl-5">a</span><span class="hl-1"> </span><span class="hl-4">=&gt;</span><br/><span class="hl-1"> </span><span class="hl-5">console</span><span class="hl-1">.</span><span class="hl-0">log</span><span class="hl-1">(</span><span class="hl-2">`[</span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">severity</span><span class="hl-11">.</span><span class="hl-0">toUpperCase</span><span class="hl-11">()</span><span class="hl-4">}</span><span class="hl-2">] </span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">type</span><span class="hl-4">}</span><span class="hl-2">: </span><span class="hl-4">${</span><span class="hl-5">a</span><span class="hl-11">.</span><span class="hl-5">message</span><span class="hl-4">}</span><span class="hl-2">`</span><span class="hl-1">)</span><br/><span class="hl-1">);</span>
898
+ </code><button type="button">Copy</button></pre>
899
+
900
+ <h3 id="concurrent-clients" class="tsd-anchor-link">Concurrent Clients<a href="#concurrent-clients" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
901
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shell</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-2">&quot;typescript-vm&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">client1</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;alice&quot;</span><span class="hl-1">);</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">client2</span><span class="hl-1"> = </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">SshClient</span><span class="hl-1">(</span><span class="hl-5">shell</span><span class="hl-1">, </span><span class="hl-2">&quot;bob&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-7">r1</span><span class="hl-1">, </span><span class="hl-7">r2</span><span class="hl-1">] = </span><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-17">Promise</span><span class="hl-1">.</span><span class="hl-0">all</span><span class="hl-1">([</span><br/><span class="hl-1"> </span><span class="hl-5">client1</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/tmp/alice.txt&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;Alice&#39;s data&quot;</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">client2</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/tmp/bob.txt&quot;</span><span class="hl-1">, </span><span class="hl-2">&quot;Bob&#39;s data&quot;</span><span class="hl-1">),</span><br/><span class="hl-1">]);</span>
902
+ </code><button type="button">Copy</button></pre>
903
+
904
+ <h3 id="bashrc" class="tsd-anchor-link">.bashrc<a href="#bashrc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
905
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/home/root/.bashrc&quot;</span><span class="hl-1">, </span><span class="hl-2">`</span><br/><span class="hl-2">export EDITOR=nano</span><br/><span class="hl-2">export PATH=&quot;/usr/local/bin:/usr/bin:/bin&quot;</span><br/><span class="hl-2">alias ll=&quot;ls -l&quot;</span><br/><span class="hl-2">echo &quot;Welcome back, root!&quot;</span><br/><span class="hl-2">`</span><span class="hl-1">.</span><span class="hl-0">trim</span><span class="hl-1">());</span><br/><span class="hl-3">// On interactive SSH login, .bashrc is sourced automatically.</span>
906
+ </code><button type="button">Copy</button></pre>
907
+
908
+ </details>
909
+ <hr>
910
+ <details>
911
+ <summary><strong>Built-in Commands (91)</strong></summary>
912
+ <p>Type <code>help</code> in the shell for a grouped, colorized listing. Type <code>help &lt;command&gt;</code> for detailed usage. Type <code>man &lt;command&gt;</code> for full manual pages — all 91 commands are documented.</p>
913
+ <h3 id="navigation" class="tsd-anchor-link">Navigation<a href="#navigation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
914
+ <table>
915
+ <thead>
916
+ <tr>
917
+ <th>Command</th>
918
+ <th>Flags</th>
919
+ <th>Description</th>
920
+ </tr>
921
+ </thead>
922
+ <tbody>
923
+ <tr>
924
+ <td><code>cd &lt;path&gt;</code></td>
925
+ <td></td>
926
+ <td>Change directory</td>
927
+ </tr>
928
+ <tr>
929
+ <td><code>ls [path]</code></td>
930
+ <td><code>-l</code> <code>-a</code></td>
931
+ <td>List directory (<code>-a</code> shows dotfiles)</td>
932
+ </tr>
933
+ <tr>
934
+ <td><code>pwd</code></td>
935
+ <td></td>
936
+ <td>Print working directory</td>
937
+ </tr>
938
+ <tr>
939
+ <td><code>tree [path]</code></td>
940
+ <td></td>
941
+ <td>ASCII directory tree</td>
942
+ </tr>
943
+ </tbody>
944
+ </table>
945
+ <h3 id="files-filesystem" class="tsd-anchor-link">Files &amp; Filesystem<a href="#files-filesystem" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
946
+ <table>
947
+ <thead>
948
+ <tr>
949
+ <th>Command</th>
950
+ <th>Flags</th>
951
+ <th>Description</th>
952
+ </tr>
953
+ </thead>
954
+ <tbody>
955
+ <tr>
956
+ <td><code>cat &lt;path...&gt;</code></td>
957
+ <td><code>-n</code> <code>-b</code></td>
958
+ <td>Concatenate and print; <code>-n</code> numbers lines, <code>-b</code> numbers non-blank</td>
959
+ </tr>
960
+ <tr>
961
+ <td><code>chmod &lt;mode&gt; &lt;file&gt;</code></td>
962
+ <td></td>
963
+ <td>Octal (<code>755</code>) or symbolic (<code>+x</code>, <code>u+x</code>, <code>go-w</code>, <code>a=rx</code>)</td>
964
+ </tr>
965
+ <tr>
966
+ <td><code>cp &lt;src&gt; &lt;dest&gt;</code></td>
967
+ <td><code>-r</code></td>
968
+ <td>Copy file or directory</td>
969
+ </tr>
970
+ <tr>
971
+ <td><code>find [path]</code></td>
972
+ <td><code>-name</code> <code>-type</code></td>
973
+ <td>Search for files</td>
974
+ </tr>
975
+ <tr>
976
+ <td><code>ln &lt;target&gt; &lt;link&gt;</code></td>
977
+ <td><code>-s</code></td>
978
+ <td>Hard or symbolic link</td>
979
+ </tr>
980
+ <tr>
981
+ <td><code>readlink &lt;path&gt;</code></td>
982
+ <td><code>-f</code></td>
983
+ <td>Print resolved path of symbolic link</td>
984
+ </tr>
985
+ <tr>
986
+ <td><code>mkdir &lt;path&gt;</code></td>
987
+ <td><code>-p</code></td>
988
+ <td>Create directory</td>
989
+ </tr>
990
+ <tr>
991
+ <td><code>mv &lt;src&gt; &lt;dest&gt;</code></td>
992
+ <td></td>
993
+ <td>Move or rename</td>
994
+ </tr>
995
+ <tr>
996
+ <td><code>nano &lt;path&gt;</code></td>
997
+ <td></td>
998
+ <td>Interactive text editor</td>
999
+ </tr>
1000
+ <tr>
1001
+ <td><code>rm &lt;path&gt;</code></td>
1002
+ <td><code>-r</code></td>
1003
+ <td>Remove file or directory</td>
1004
+ </tr>
1005
+ <tr>
1006
+ <td><code>stat &lt;path&gt;</code></td>
1007
+ <td><code>-c &lt;format&gt;</code></td>
1008
+ <td>Display file status (inode, size, mode, timestamps)</td>
1009
+ </tr>
1010
+ <tr>
1011
+ <td><code>touch &lt;path&gt;</code></td>
1012
+ <td></td>
1013
+ <td>Create or update file</td>
1014
+ </tr>
1015
+ </tbody>
1016
+ </table>
1017
+ <h3 id="text-processing" class="tsd-anchor-link">Text Processing<a href="#text-processing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1018
+ <table>
1019
+ <thead>
1020
+ <tr>
1021
+ <th>Command</th>
1022
+ <th>Flags</th>
1023
+ <th>Description</th>
1024
+ </tr>
1025
+ </thead>
1026
+ <tbody>
1027
+ <tr>
1028
+ <td><code>awk [-F &lt;sep&gt;] '&lt;prog&gt;'</code></td>
1029
+ <td></td>
1030
+ <td>Pattern scanning</td>
1031
+ </tr>
1032
+ <tr>
1033
+ <td><code>base64</code></td>
1034
+ <td><code>-d</code></td>
1035
+ <td>Encode/decode base64</td>
1036
+ </tr>
1037
+ <tr>
1038
+ <td><code>cut</code></td>
1039
+ <td><code>-d</code> <code>-f</code></td>
1040
+ <td>Remove sections from lines</td>
1041
+ </tr>
1042
+ <tr>
1043
+ <td><code>diff &lt;f1&gt; &lt;f2&gt;</code></td>
1044
+ <td></td>
1045
+ <td>Compare files line by line</td>
1046
+ </tr>
1047
+ <tr>
1048
+ <td><code>grep &lt;pattern&gt; [files]</code></td>
1049
+ <td><code>-i</code> <code>-v</code> <code>-n</code> <code>-r</code></td>
1050
+ <td>Search file content</td>
1051
+ </tr>
1052
+ <tr>
1053
+ <td><code>head [files]</code></td>
1054
+ <td><code>-n &lt;N&gt;</code></td>
1055
+ <td>First N lines</td>
1056
+ </tr>
1057
+ <tr>
1058
+ <td><code>sed -e 's/pat/rep/[g]'</code></td>
1059
+ <td><code>-i</code></td>
1060
+ <td>Stream editor</td>
1061
+ </tr>
1062
+ <tr>
1063
+ <td><code>sort [files]</code></td>
1064
+ <td><code>-r</code> <code>-n</code> <code>-u</code></td>
1065
+ <td>Sort lines</td>
1066
+ </tr>
1067
+ <tr>
1068
+ <td><code>tail [files]</code></td>
1069
+ <td><code>-n &lt;N&gt;</code></td>
1070
+ <td>Last N lines</td>
1071
+ </tr>
1072
+ <tr>
1073
+ <td><code>tee [files]</code></td>
1074
+ <td><code>-a</code></td>
1075
+ <td>Read stdin, write to stdout and files</td>
1076
+ </tr>
1077
+ <tr>
1078
+ <td><code>tr &lt;set1&gt; [set2]</code></td>
1079
+ <td><code>-d</code></td>
1080
+ <td>Translate or delete characters</td>
1081
+ </tr>
1082
+ <tr>
1083
+ <td><code>uniq</code></td>
1084
+ <td><code>-c</code> <code>-d</code> <code>-u</code></td>
1085
+ <td>Filter repeated lines</td>
1086
+ </tr>
1087
+ <tr>
1088
+ <td><code>wc [files]</code></td>
1089
+ <td><code>-l</code> <code>-w</code> <code>-c</code></td>
1090
+ <td>Word/line/byte count</td>
1091
+ </tr>
1092
+ <tr>
1093
+ <td><code>xargs [cmd]</code></td>
1094
+ <td></td>
1095
+ <td>Build and execute commands from stdin</td>
1096
+ </tr>
1097
+ </tbody>
1098
+ </table>
1099
+ <h3 id="archive-compression" class="tsd-anchor-link">Archive &amp; Compression<a href="#archive-compression" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1100
+ <table>
1101
+ <thead>
1102
+ <tr>
1103
+ <th>Command</th>
1104
+ <th>Flags</th>
1105
+ <th>Description</th>
1106
+ </tr>
1107
+ </thead>
1108
+ <tbody>
1109
+ <tr>
1110
+ <td><code>gzip &lt;file&gt;</code> / <code>gunzip &lt;file&gt;</code></td>
1111
+ <td></td>
1112
+ <td>Compress / decompress</td>
1113
+ </tr>
1114
+ <tr>
1115
+ <td><code>tar &lt;archive&gt; [files]</code></td>
1116
+ <td><code>-czf</code> <code>-xzf</code> <code>-tf</code></td>
1117
+ <td>Archive utility</td>
1118
+ </tr>
1119
+ </tbody>
1120
+ </table>
1121
+ <h3 id="system" class="tsd-anchor-link">System<a href="#system" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1122
+ <table>
1123
+ <thead>
1124
+ <tr>
1125
+ <th>Command</th>
1126
+ <th>Flags</th>
1127
+ <th>Description</th>
1128
+ </tr>
1129
+ </thead>
1130
+ <tbody>
1131
+ <tr>
1132
+ <td><code>date</code></td>
1133
+ <td><code>+format</code></td>
1134
+ <td>Current date and time</td>
1135
+ </tr>
1136
+ <tr>
1137
+ <td><code>df</code></td>
1138
+ <td><code>-h</code></td>
1139
+ <td>Filesystem disk space</td>
1140
+ </tr>
1141
+ <tr>
1142
+ <td><code>du [path]</code></td>
1143
+ <td><code>-h</code> <code>-s</code></td>
1144
+ <td>Estimate file space</td>
1145
+ </tr>
1146
+ <tr>
1147
+ <td><code>free</code></td>
1148
+ <td><code>-h</code> <code>-m</code> <code>-g</code></td>
1149
+ <td>Memory usage (real host data)</td>
1150
+ </tr>
1151
+ <tr>
1152
+ <td><code>groups [user]</code></td>
1153
+ <td></td>
1154
+ <td>Group memberships</td>
1155
+ </tr>
1156
+ <tr>
1157
+ <td><code>hostname</code></td>
1158
+ <td></td>
1159
+ <td>Print hostname</td>
1160
+ </tr>
1161
+ <tr>
1162
+ <td><code>htop</code></td>
1163
+ <td></td>
1164
+ <td>System monitor (mock)</td>
1165
+ </tr>
1166
+ <tr>
1167
+ <td><code>id [user]</code></td>
1168
+ <td></td>
1169
+ <td>User identity (uid/gid/groups)</td>
1170
+ </tr>
1171
+ <tr>
1172
+ <td><code>kill [-9] &lt;pid&gt;</code></td>
1173
+ <td></td>
1174
+ <td>Send signal (mock)</td>
1175
+ </tr>
1176
+ <tr>
1177
+ <td><code>lsb_release</code></td>
1178
+ <td><code>-a</code> <code>-i</code> <code>-d</code> <code>-r</code> <code>-c</code></td>
1179
+ <td>Distribution info</td>
1180
+ </tr>
1181
+ <tr>
1182
+ <td><code>neofetch</code></td>
1183
+ <td></td>
1184
+ <td>System info (real package count and uptime)</td>
1185
+ </tr>
1186
+ <tr>
1187
+ <td><code>node</code></td>
1188
+ <td><code>--version</code> <code>-e</code> <code>-p</code></td>
1189
+ <td>Virtual JS runtime; <strong>requires <code>apt install nodejs</code></strong></td>
1190
+ </tr>
1191
+ <tr>
1192
+ <td><code>npm</code></td>
1193
+ <td><code>--version</code> <code>list</code> <code>version</code></td>
1194
+ <td>Node.js package manager (install/run stubbed); <strong>requires <code>apt install npm</code></strong></td>
1195
+ </tr>
1196
+ <tr>
1197
+ <td><code>npx</code></td>
1198
+ <td><code>--version</code></td>
1199
+ <td>Node.js package runner (stubbed); <strong>requires <code>apt install npm</code></strong></td>
1200
+ </tr>
1201
+ <tr>
1202
+ <td><code>ping [-c &lt;n&gt;] &lt;host&gt;</code></td>
1203
+ <td></td>
1204
+ <td>ICMP ECHO_REQUEST (mock)</td>
1205
+ </tr>
1206
+ <tr>
1207
+ <td><code>ps</code></td>
1208
+ <td><code>-a</code> <code>-u</code> <code>-x</code> <code>aux</code></td>
1209
+ <td>Process status</td>
1210
+ </tr>
1211
+ <tr>
1212
+ <td><code>python3</code></td>
1213
+ <td><code>--version</code> <code>-c</code> <code>-V</code></td>
1214
+ <td>Virtual Python 3 interpreter; alias <code>python</code>; <strong>requires <code>apt install python3</code></strong></td>
1215
+ </tr>
1216
+ <tr>
1217
+ <td><code>sleep &lt;seconds&gt;</code></td>
1218
+ <td></td>
1219
+ <td>Delay execution</td>
1220
+ </tr>
1221
+ <tr>
1222
+ <td><code>uname</code></td>
1223
+ <td><code>-a</code> <code>-r</code> <code>-m</code></td>
1224
+ <td>System information</td>
1225
+ </tr>
1226
+ <tr>
1227
+ <td><code>uptime</code></td>
1228
+ <td><code>-p</code> <code>-s</code></td>
1229
+ <td>Running time</td>
1230
+ </tr>
1231
+ <tr>
1232
+ <td><code>who</code></td>
1233
+ <td></td>
1234
+ <td>Active sessions</td>
1235
+ </tr>
1236
+ <tr>
1237
+ <td><code>whoami</code></td>
1238
+ <td></td>
1239
+ <td>Current user</td>
1240
+ </tr>
1241
+ </tbody>
1242
+ </table>
1243
+ <h3 id="network" class="tsd-anchor-link">Network<a href="#network" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1244
+ <table>
1245
+ <thead>
1246
+ <tr>
1247
+ <th>Command</th>
1248
+ <th>Flags</th>
1249
+ <th>Description</th>
1250
+ </tr>
1251
+ </thead>
1252
+ <tbody>
1253
+ <tr>
1254
+ <td><code>curl &lt;url&gt;</code></td>
1255
+ <td><code>-o</code> <code>-X</code> <code>-d</code> <code>-H</code> <code>-s</code> <code>-I</code> <code>-L</code> <code>-v</code></td>
1256
+ <td>HTTP client (pure <code>fetch()</code>)</td>
1257
+ </tr>
1258
+ <tr>
1259
+ <td><code>wget &lt;url&gt;</code></td>
1260
+ <td><code>-O</code> <code>-P</code> <code>-q</code></td>
1261
+ <td>File downloader (pure <code>fetch()</code>)</td>
1262
+ </tr>
1263
+ </tbody>
1264
+ </table>
1265
+ <h3 id="shell-scripting-1" class="tsd-anchor-link">Shell &amp; Scripting<a href="#shell-scripting-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1266
+ <table>
1267
+ <thead>
1268
+ <tr>
1269
+ <th>Command</th>
1270
+ <th>Flags</th>
1271
+ <th>Description</th>
1272
+ </tr>
1273
+ </thead>
1274
+ <tbody>
1275
+ <tr>
1276
+ <td><code>alias [name=value]</code></td>
1277
+ <td></td>
1278
+ <td>Define or display aliases</td>
1279
+ </tr>
1280
+ <tr>
1281
+ <td><code>clear</code></td>
1282
+ <td></td>
1283
+ <td>Clear terminal screen</td>
1284
+ </tr>
1285
+ <tr>
1286
+ <td><code>declare [name=value]</code></td>
1287
+ <td><code>-i</code> <code>-r</code> <code>-x</code></td>
1288
+ <td>Declare variables; aliases <code>local</code>, <code>typeset</code></td>
1289
+ </tr>
1290
+ <tr>
1291
+ <td><code>echo &lt;text&gt;</code></td>
1292
+ <td><code>-n</code> <code>-e</code></td>
1293
+ <td>Display text; <code>-e</code> interprets <code>\n</code> <code>\t</code> <code>\r</code> <code>\\</code></td>
1294
+ </tr>
1295
+ <tr>
1296
+ <td><code>env</code></td>
1297
+ <td></td>
1298
+ <td>Print session environment</td>
1299
+ </tr>
1300
+ <tr>
1301
+ <td><code>exit [code]</code></td>
1302
+ <td></td>
1303
+ <td>Exit session</td>
1304
+ </tr>
1305
+ <tr>
1306
+ <td><code>export NAME=VALUE</code></td>
1307
+ <td></td>
1308
+ <td>Set shell variable</td>
1309
+ </tr>
1310
+ <tr>
1311
+ <td><code>false</code></td>
1312
+ <td></td>
1313
+ <td>Return exit code 1</td>
1314
+ </tr>
1315
+ <tr>
1316
+ <td><code>help [command]</code></td>
1317
+ <td></td>
1318
+ <td>List commands or show command usage</td>
1319
+ </tr>
1320
+ <tr>
1321
+ <td><code>history [n]</code></td>
1322
+ <td></td>
1323
+ <td>Command history</td>
1324
+ </tr>
1325
+ <tr>
1326
+ <td><code>man &lt;command&gt;</code></td>
1327
+ <td></td>
1328
+ <td>Command reference manual</td>
1329
+ </tr>
1330
+ <tr>
1331
+ <td><code>printf &lt;fmt&gt; [args...]</code></td>
1332
+ <td></td>
1333
+ <td>Format and print (<code>%s</code> <code>%d</code> <code>%f</code> <code>%x</code> <code>\n</code> <code>\t</code>)</td>
1334
+ </tr>
1335
+ <tr>
1336
+ <td><code>read [-r] &lt;var...&gt;</code></td>
1337
+ <td><code>-r</code> <code>-p</code></td>
1338
+ <td>Read stdin into variable(s)</td>
1339
+ </tr>
1340
+ <tr>
1341
+ <td><code>return [n]</code></td>
1342
+ <td></td>
1343
+ <td>Return from shell function</td>
1344
+ </tr>
1345
+ <tr>
1346
+ <td><code>set [VAR=val]</code></td>
1347
+ <td></td>
1348
+ <td>Display or set shell variables</td>
1349
+ </tr>
1350
+ <tr>
1351
+ <td><code>sh</code></td>
1352
+ <td><code>-c &lt;script&gt;</code> <code>[file]</code></td>
1353
+ <td>Execute shell script — <code>if</code>/<code>for</code>/<code>while</code>/<code>case</code>/functions, <code>$((expr))</code>, single-quote-safe</td>
1354
+ </tr>
1355
+ <tr>
1356
+ <td><code>shift [n]</code></td>
1357
+ <td></td>
1358
+ <td>Shift positional parameters</td>
1359
+ </tr>
1360
+ <tr>
1361
+ <td><code>source &lt;file&gt;</code></td>
1362
+ <td></td>
1363
+ <td>Execute file in current env; alias <code>.</code></td>
1364
+ </tr>
1365
+ <tr>
1366
+ <td><code>test &lt;expr&gt;</code> / <code>[ &lt;expr&gt; ]</code></td>
1367
+ <td></td>
1368
+ <td>POSIX conditional: <code>-f</code> <code>-d</code> <code>-e</code> <code>-z</code> <code>-n</code> <code>-x</code> <code>-s</code> <code>=</code> <code>!=</code> <code>-eq</code> <code>-lt</code> <code>-gt</code> <code>-le</code> <code>-ge</code> <code>!</code> <code>-a</code> <code>-o</code></td>
1369
+ </tr>
1370
+ <tr>
1371
+ <td><code>trap [action] [signal]</code></td>
1372
+ <td></td>
1373
+ <td>Signal handlers; supports <code>EXIT</code></td>
1374
+ </tr>
1375
+ <tr>
1376
+ <td><code>true</code></td>
1377
+ <td></td>
1378
+ <td>Return exit code 0</td>
1379
+ </tr>
1380
+ <tr>
1381
+ <td><code>type &lt;command&gt;</code></td>
1382
+ <td></td>
1383
+ <td>Describe command interpretation</td>
1384
+ </tr>
1385
+ <tr>
1386
+ <td><code>unalias &lt;name&gt;</code></td>
1387
+ <td><code>-a</code></td>
1388
+ <td>Remove aliases</td>
1389
+ </tr>
1390
+ <tr>
1391
+ <td><code>unset &lt;VAR&gt;</code></td>
1392
+ <td></td>
1393
+ <td>Remove shell variable</td>
1394
+ </tr>
1395
+ <tr>
1396
+ <td><code>which &lt;command&gt;</code></td>
1397
+ <td></td>
1398
+ <td>Locate command in <code>$PATH</code></td>
1399
+ </tr>
1400
+ </tbody>
1401
+ </table>
1402
+ <h3 id="package-management" class="tsd-anchor-link">Package Management<a href="#package-management" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1403
+ <table>
1404
+ <thead>
1405
+ <tr>
1406
+ <th>Command</th>
1407
+ <th>Flags</th>
1408
+ <th>Description</th>
1409
+ </tr>
1410
+ </thead>
1411
+ <tbody>
1412
+ <tr>
1413
+ <td><code>apt &lt;cmd&gt; [pkg...]</code></td>
1414
+ <td></td>
1415
+ <td><code>install</code>, <code>remove</code>, <code>purge</code>, <code>update</code>, <code>upgrade</code>, <code>search</code>, <code>show</code>, <code>list</code></td>
1416
+ </tr>
1417
+ <tr>
1418
+ <td><code>apt-get</code></td>
1419
+ <td></td>
1420
+ <td>Alias for <code>apt</code></td>
1421
+ </tr>
1422
+ <tr>
1423
+ <td><code>apt-cache &lt;cmd&gt;</code></td>
1424
+ <td></td>
1425
+ <td><code>search</code>, <code>show</code>, <code>policy</code></td>
1426
+ </tr>
1427
+ <tr>
1428
+ <td><code>dpkg</code></td>
1429
+ <td><code>-l</code> <code>-s</code> <code>-L</code> <code>-r</code> <code>-P</code></td>
1430
+ <td>Low-level package tool</td>
1431
+ </tr>
1432
+ <tr>
1433
+ <td><code>dpkg-query</code></td>
1434
+ <td><code>-W</code> <code>-l</code></td>
1435
+ <td>Show installed package info</td>
1436
+ </tr>
1437
+ </tbody>
1438
+ </table>
1439
+ <h3 id="users-permissions" class="tsd-anchor-link">Users &amp; Permissions<a href="#users-permissions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1440
+ <table>
1441
+ <thead>
1442
+ <tr>
1443
+ <th>Command</th>
1444
+ <th>Flags</th>
1445
+ <th>Description</th>
1446
+ </tr>
1447
+ </thead>
1448
+ <tbody>
1449
+ <tr>
1450
+ <td><code>adduser &lt;name&gt; &lt;pass&gt;</code></td>
1451
+ <td></td>
1452
+ <td>Create user (root only)</td>
1453
+ </tr>
1454
+ <tr>
1455
+ <td><code>deluser &lt;name&gt;</code></td>
1456
+ <td></td>
1457
+ <td>Delete user (root only)</td>
1458
+ </tr>
1459
+ <tr>
1460
+ <td><code>passwd [user]</code></td>
1461
+ <td></td>
1462
+ <td>Change password</td>
1463
+ </tr>
1464
+ <tr>
1465
+ <td><code>su [user]</code></td>
1466
+ <td></td>
1467
+ <td>Switch user</td>
1468
+ </tr>
1469
+ <tr>
1470
+ <td><code>sudo &lt;cmd&gt;</code></td>
1471
+ <td><code>-i</code></td>
1472
+ <td>Run as root</td>
1473
+ </tr>
1474
+ </tbody>
1475
+ </table>
1476
+ <p><strong>ℹ️ All 91 built-in commands include complete JSDoc documentation</strong> with <code>@category</code> and <code>@params</code> tags. See <a href="media/commands">src/commands/</a> for source code and inline documentation.</p>
1477
+ <p>Custom commands: <code>shell.addCommand(name, params, callback)</code>.</p>
1478
+ </details>
1479
+ <hr>
1480
+ <details>
1481
+ <summary><strong>Shell Scripting</strong></summary>
1482
+ <p>The interpreter supports a POSIX sh subset via <code>sh -c '...'</code>, <code>sh &lt;file&gt;</code>, or interactive session.</p>
1483
+ <h3 id="operators-and-redirections" class="tsd-anchor-link">Operators and Redirections<a href="#operators-and-redirections" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1484
+ <pre><code class="bash"><span class="hl-0">mkdir</span><span class="hl-1"> </span><span class="hl-2">/app</span><span class="hl-1"> &amp;&amp; </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;created&quot;</span><span class="hl-1"> </span><span class="hl-3"># &amp;&amp; — only if previous succeeds</span><br/><span class="hl-0">rm</span><span class="hl-1"> </span><span class="hl-2">/missing</span><span class="hl-1"> || </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;not found&quot;</span><span class="hl-1"> </span><span class="hl-3"># || — only if previous fails</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">a</span><span class="hl-1">; </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">b</span><span class="hl-1">; </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">c</span><span class="hl-1"> </span><span class="hl-3"># ; — always all three</span><br/><br/><span class="hl-0">cat</span><span class="hl-1"> </span><span class="hl-2">/etc/hosts</span><span class="hl-1"> | </span><span class="hl-0">grep</span><span class="hl-1"> </span><span class="hl-2">local</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;hello&quot;</span><span class="hl-1"> &gt; </span><span class="hl-2">/tmp/out.txt</span><span class="hl-1"> </span><span class="hl-3"># overwrite</span><br/><span class="hl-0">cat</span><span class="hl-1"> </span><span class="hl-2">/tmp/out.txt</span><span class="hl-1"> &gt;&gt; </span><span class="hl-2">/tmp/log.txt</span><span class="hl-1"> </span><span class="hl-3"># append</span>
1485
+ </code><button type="button">Copy</button></pre>
1486
+
1487
+ <h3 id="variable-expansion" class="tsd-anchor-link">Variable Expansion<a href="#variable-expansion" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1488
+ <pre><code class="bash"><span class="hl-4">export</span><span class="hl-1"> </span><span class="hl-5">NAME</span><span class="hl-1">=</span><span class="hl-5">world</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Hello </span><span class="hl-5">$NAME</span><span class="hl-2">&quot;</span><span class="hl-1"> </span><span class="hl-3"># Hello world</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;${</span><span class="hl-5">NAME</span><span class="hl-1">:-</span><span class="hl-5">fallback</span><span class="hl-2">}&quot;</span><span class="hl-1"> </span><span class="hl-3"># world (or fallback if unset)</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;${</span><span class="hl-5">UNSET</span><span class="hl-1">:-</span><span class="hl-5">default</span><span class="hl-2">}&quot;</span><span class="hl-1"> </span><span class="hl-3"># default</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;${</span><span class="hl-5">NAME</span><span class="hl-1">:</span><span class="hl-2">+</span><span class="hl-5">alternate</span><span class="hl-2">}&quot;</span><span class="hl-1"> </span><span class="hl-3"># alternate (only if NAME is set)</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;${</span><span class="hl-5">UNSET</span><span class="hl-1">:=</span><span class="hl-5">assigned</span><span class="hl-2">}&quot;</span><span class="hl-1"> </span><span class="hl-3"># assigns and returns &quot;assigned&quot;</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;${</span><span class="hl-1">#</span><span class="hl-5">NAME</span><span class="hl-2">}&quot;</span><span class="hl-1"> </span><span class="hl-3"># 5 (string length)</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;</span><span class="hl-4">$?</span><span class="hl-2">&quot;</span><span class="hl-1"> </span><span class="hl-3"># last exit code</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">~</span><span class="hl-1"> </span><span class="hl-3"># /home/&lt;user&gt; (tilde expansion)</span>
1489
+ </code><button type="button">Copy</button></pre>
1490
+
1491
+ <blockquote>
1492
+ <p><strong>Single-quote isolation</strong> — <code>$VAR</code> and <code>$((...))</code> are never expanded inside <code>'...'</code>.</p>
1493
+ </blockquote>
1494
+ <h3 id="arithmetic" class="tsd-anchor-link">Arithmetic<a href="#arithmetic" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1495
+ <pre><code class="bash"><span class="hl-0">echo</span><span class="hl-1"> $((</span><span class="hl-0">2</span><span class="hl-1"> </span><span class="hl-2">+</span><span class="hl-1"> </span><span class="hl-8">3</span><span class="hl-1">)) </span><span class="hl-3"># 5</span><br/><span class="hl-5">X</span><span class="hl-1">=</span><span class="hl-2">4</span><span class="hl-1">; </span><span class="hl-0">echo</span><span class="hl-1"> $((</span><span class="hl-0">X</span><span class="hl-1"> </span><span class="hl-4">*</span><span class="hl-1"> </span><span class="hl-8">2</span><span class="hl-1">)) </span><span class="hl-3"># 8</span><br/><span class="hl-5">i</span><span class="hl-1">=</span><span class="hl-2">0</span><span class="hl-1">; </span><span class="hl-5">i</span><span class="hl-1">=$((</span><span class="hl-0">i</span><span class="hl-1"> </span><span class="hl-2">+</span><span class="hl-1"> </span><span class="hl-8">1</span><span class="hl-1">)) </span><span class="hl-3"># increment</span>
1496
+ </code><button type="button">Copy</button></pre>
1497
+
1498
+ <h3 id="conditionals" class="tsd-anchor-link">Conditionals<a href="#conditionals" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1499
+ <pre><code class="bash"><span class="hl-6">if</span><span class="hl-1"> [ -f /etc/config ]; </span><span class="hl-6">then</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;config exists&quot;</span><br/><span class="hl-6">elif</span><span class="hl-1"> [ -d /etc ]; </span><span class="hl-6">then</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;etc is a directory&quot;</span><br/><span class="hl-6">else</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;nothing found&quot;</span><br/><span class="hl-6">fi</span><br/><br/><span class="hl-1">[ </span><span class="hl-2">&quot;</span><span class="hl-5">$USER</span><span class="hl-2">&quot;</span><span class="hl-1"> = </span><span class="hl-2">&quot;root&quot;</span><span class="hl-1"> ] &amp;&amp; </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;root&quot;</span><br/><span class="hl-1">[ </span><span class="hl-5">$COUNT</span><span class="hl-1"> -gt </span><span class="hl-8">10</span><span class="hl-1"> ] &amp;&amp; </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;large&quot;</span>
1500
+ </code><button type="button">Copy</button></pre>
1501
+
1502
+ <h3 id="loops" class="tsd-anchor-link">Loops<a href="#loops" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1503
+ <pre><code class="bash"><span class="hl-6">for</span><span class="hl-1"> </span><span class="hl-5">name</span><span class="hl-1"> </span><span class="hl-6">in</span><span class="hl-1"> </span><span class="hl-2">alice</span><span class="hl-1"> </span><span class="hl-2">bob</span><span class="hl-1"> </span><span class="hl-2">charlie</span><span class="hl-1">; </span><span class="hl-6">do</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Hello </span><span class="hl-5">$name</span><span class="hl-2">&quot;</span><br/><span class="hl-6">done</span><br/><br/><span class="hl-5">COUNT</span><span class="hl-1">=</span><span class="hl-2">0</span><br/><span class="hl-6">while</span><span class="hl-1"> [ </span><span class="hl-5">$COUNT</span><span class="hl-1"> -lt </span><span class="hl-8">3</span><span class="hl-1"> ]; </span><span class="hl-6">do</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Count: </span><span class="hl-5">$COUNT</span><span class="hl-2">&quot;</span><br/><span class="hl-1"> </span><span class="hl-5">COUNT</span><span class="hl-1">=$((</span><span class="hl-0">COUNT</span><span class="hl-1"> </span><span class="hl-2">+</span><span class="hl-1"> </span><span class="hl-8">1</span><span class="hl-1">))</span><br/><span class="hl-6">done</span>
1504
+ </code><button type="button">Copy</button></pre>
1505
+
1506
+ <h3 id="functions-and-case" class="tsd-anchor-link">Functions and case<a href="#functions-and-case" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1507
+ <pre><code class="bash"><span class="hl-0">greet</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Hello, </span><span class="hl-5">$1</span><span class="hl-2">!&quot;</span><br/><span class="hl-1">}</span><br/><span class="hl-0">greet</span><span class="hl-1"> </span><span class="hl-2">world</span><br/><br/><span class="hl-6">case</span><span class="hl-1"> </span><span class="hl-2">&quot;</span><span class="hl-5">$1</span><span class="hl-2">&quot;</span><span class="hl-1"> </span><span class="hl-6">in</span><br/><span class="hl-1"> </span><span class="hl-14">start</span><span class="hl-1">) </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Starting...&quot;</span><span class="hl-1"> ;;</span><br/><span class="hl-1"> </span><span class="hl-14">stop</span><span class="hl-1">) </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Stopping...&quot;</span><span class="hl-1"> ;;</span><br/><span class="hl-1"> *) </span><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Usage: </span><span class="hl-5">$0</span><span class="hl-2"> {start|stop}&quot;</span><span class="hl-1"> ;;</span><br/><span class="hl-6">esac</span>
1508
+ </code><button type="button">Copy</button></pre>
1509
+
1510
+ <h3 id="script-files" class="tsd-anchor-link">Script Files<a href="#script-files" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1511
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-5">vfs</span><span class="hl-1">.</span><span class="hl-0">writeFile</span><span class="hl-1">(</span><span class="hl-2">&quot;/usr/local/bin/setup.sh&quot;</span><span class="hl-1">, </span><span class="hl-2">`</span><br/><span class="hl-2">#!/bin/sh</span><br/><span class="hl-2">for dir in config logs tmp; do</span><br/><span class="hl-2"> mkdir /app/$dir</span><br/><span class="hl-2">done</span><br/><span class="hl-2">`</span><span class="hl-1">);</span><br/><span class="hl-6">await</span><span class="hl-1"> </span><span class="hl-5">client</span><span class="hl-1">.</span><span class="hl-0">exec</span><span class="hl-1">(</span><span class="hl-2">&quot;sh /usr/local/bin/setup.sh&quot;</span><span class="hl-1">);</span>
1512
+ </code><button type="button">Copy</button></pre>
1513
+
1514
+ <h3 id="bashrc-1" class="tsd-anchor-link">.bashrc<a href="#bashrc-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1515
+ <p>Sourced automatically on every interactive session from <code>/home/&lt;user&gt;/.bashrc</code>:</p>
1516
+ <pre><code class="bash"><span class="hl-4">export</span><span class="hl-1"> </span><span class="hl-5">EDITOR</span><span class="hl-1">=</span><span class="hl-5">nano</span><br/><span class="hl-4">alias</span><span class="hl-1"> </span><span class="hl-5">ll</span><span class="hl-1">=</span><span class="hl-2">&quot;ls -l&quot;</span><br/><span class="hl-0">echo</span><span class="hl-1"> </span><span class="hl-2">&quot;Welcome, </span><span class="hl-5">$USER</span><span class="hl-2">!&quot;</span>
1517
+ </code><button type="button">Copy</button></pre>
1518
+
1519
+ </details>
1520
+ <hr>
1521
+ <details>
1522
+ <summary><strong>Linux Rootfs &amp; VFS PATH Resolution</strong></summary>
1523
+ <h3 id="directory-layout" class="tsd-anchor-link">Directory Layout<a href="#directory-layout" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1524
+ <p>On every <code>VirtualShell</code> init, a realistic Linux hierarchy is bootstrapped idempotently:</p>
1525
+ <pre><code><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">bin</span><span class="hl-1"> -&gt; </span><span class="hl-5">usr</span><span class="hl-1">/</span><span class="hl-0">bin</span><span class="hl-1"> (</span><span class="hl-5">symlink</span><span class="hl-1">, </span><span class="hl-5">Debian</span><span class="hl-1">-</span><span class="hl-5">style</span><span class="hl-1">)</span><br/><span class="hl-1">├── </span><span class="hl-5">sbin</span><span class="hl-1"> -&gt; </span><span class="hl-5">usr</span><span class="hl-1">/</span><span class="hl-0">sbin</span><span class="hl-1"> (</span><span class="hl-5">symlink</span><span class="hl-1">, </span><span class="hl-5">Debian</span><span class="hl-1">-</span><span class="hl-5">style</span><span class="hl-1">)</span><br/><span class="hl-1">├── </span><span class="hl-5">lib</span><span class="hl-1">/ (</span><span class="hl-7">ELF</span><span class="hl-1"> </span><span class="hl-5">stub</span><span class="hl-1">)</span><br/><span class="hl-1">├── </span><span class="hl-5">lib</span><span class="hl-1">/</span><span class="hl-5">modules</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">lib</span><span class="hl-1">/</span><span class="hl-5">x86_64</span><span class="hl-1">-</span><span class="hl-5">linux</span><span class="hl-1">-</span><span class="hl-5">gnu</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">lib64</span><span class="hl-1"> -&gt; </span><span class="hl-5">usr</span><span class="hl-1">/</span><span class="hl-0">lib64</span><span class="hl-1"> (</span><span class="hl-5">symlink</span><span class="hl-1">, </span><span class="hl-5">Debian</span><span class="hl-1">-</span><span class="hl-5">style</span><span class="hl-1">)</span><br/><span class="hl-1">├── </span><span class="hl-5">initrd</span><span class="hl-1">.</span><span class="hl-5">img</span><span class="hl-1"> -&gt; </span><span class="hl-5">boot</span><span class="hl-1">/</span><span class="hl-5">initrd</span><span class="hl-1">.</span><span class="hl-5">img</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt;</span><br/><span class="hl-1">├── </span><span class="hl-5">initrd</span><span class="hl-1">.</span><span class="hl-5">img</span><span class="hl-1">.</span><span class="hl-5">old</span><span class="hl-1"> -&gt; </span><span class="hl-5">boot</span><span class="hl-1">/</span><span class="hl-5">initrd</span><span class="hl-1">.</span><span class="hl-5">img</span><span class="hl-1">-&lt;</span><span class="hl-17">prev</span><span class="hl-1">&gt;</span><br/><span class="hl-1">├── </span><span class="hl-5">vmlinuz</span><span class="hl-1"> -&gt; </span><span class="hl-5">boot</span><span class="hl-1">/</span><span class="hl-5">vmlinuz</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt;</span><br/><span class="hl-1">├── </span><span class="hl-5">vmlinuz</span><span class="hl-1">.</span><span class="hl-5">old</span><span class="hl-1"> -&gt; </span><span class="hl-5">boot</span><span class="hl-1">/</span><span class="hl-5">vmlinuz</span><span class="hl-1">-&lt;</span><span class="hl-17">prev</span><span class="hl-1">&gt;</span><br/><span class="hl-1">├── </span><span class="hl-5">lost</span><span class="hl-1">+</span><span class="hl-5">found</span><span class="hl-1">/ (</span><span class="hl-5">mode</span><span class="hl-1"> </span><span class="hl-8">0o700</span><span class="hl-1">, </span><span class="hl-5">ext4</span><span class="hl-1"> </span><span class="hl-5">fsck</span><span class="hl-1"> </span><span class="hl-5">dir</span><span class="hl-1">)</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">boot</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">grub</span><span class="hl-1">/</span><br/><span class="hl-1">│ │ └── </span><span class="hl-5">grub</span><span class="hl-1">.</span><span class="hl-5">cfg</span><span class="hl-1"> </span><span class="hl-5">virtual</span><span class="hl-1"> </span><span class="hl-5">bootloader</span><span class="hl-1"> </span><span class="hl-5">config</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">vmlinuz</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt; </span><span class="hl-5">kernel</span><span class="hl-1"> </span><span class="hl-5">stub</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">initrd</span><span class="hl-1">.</span><span class="hl-5">img</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt; </span><span class="hl-5">initrd</span><span class="hl-1"> </span><span class="hl-5">stub</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">System</span><span class="hl-1">.</span><span class="hl-5">map</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt;</span><br/><span class="hl-1">│ └── </span><span class="hl-5">config</span><span class="hl-1">-&lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt;</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">dev</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-4">null</span><span class="hl-1"> / </span><span class="hl-5">zero</span><span class="hl-1"> / </span><span class="hl-0">full</span><span class="hl-1"> (</span><span class="hl-8">0o666</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">random</span><span class="hl-1"> / </span><span class="hl-0">urandom</span><span class="hl-1"> (</span><span class="hl-8">0o444</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-0">mem</span><span class="hl-1"> (</span><span class="hl-8">0o640</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">console</span><span class="hl-1"> / </span><span class="hl-5">tty</span><span class="hl-1"> / </span><span class="hl-5">tty0</span><span class="hl-1"> / </span><span class="hl-5">tty1</span><span class="hl-1"> / </span><span class="hl-5">ttyS0</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">sda</span><span class="hl-1"> / </span><span class="hl-5">sda1</span><span class="hl-1"> / </span><span class="hl-5">sda2</span><span class="hl-1"> </span><span class="hl-5">block</span><span class="hl-1"> </span><span class="hl-5">device</span><span class="hl-1"> </span><span class="hl-5">stubs</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">loop0</span><span class="hl-1">-</span><span class="hl-5">loop7</span><span class="hl-1"> + </span><span class="hl-5">loop</span><span class="hl-1">-</span><span class="hl-5">control</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">stdin</span><span class="hl-1"> / </span><span class="hl-5">stdout</span><span class="hl-1"> / </span><span class="hl-5">stderr</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">pts</span><span class="hl-1">/</span><br/><span class="hl-1">│ └── </span><span class="hl-5">shm</span><span class="hl-1">/</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">etc</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">apt</span><span class="hl-1">/</span><span class="hl-5">sources</span><span class="hl-1">.</span><span class="hl-5">list</span><span class="hl-1"> + </span><span class="hl-5">sources</span><span class="hl-1">.</span><span class="hl-5">list</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">cron</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">init</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">ld</span><span class="hl-1">.</span><span class="hl-5">so</span><span class="hl-1">.</span><span class="hl-5">conf</span><span class="hl-1"> + </span><span class="hl-5">ld</span><span class="hl-1">.</span><span class="hl-5">so</span><span class="hl-1">.</span><span class="hl-5">conf</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/</span><span class="hl-5">x86_64</span><span class="hl-1">-</span><span class="hl-5">linux</span><span class="hl-1">-</span><span class="hl-5">gnu</span><span class="hl-1">.</span><span class="hl-5">conf</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">network</span><span class="hl-1">/</span><span class="hl-5">interfaces</span><span class="hl-1"> </span><span class="hl-5">lo</span><span class="hl-1"> + </span><span class="hl-0">eth0</span><span class="hl-1"> (</span><span class="hl-7">DHCP</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">pam</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/ </span><span class="hl-5">common</span><span class="hl-1">-</span><span class="hl-5">auth</span><span class="hl-1">|</span><span class="hl-5">account</span><span class="hl-1">|</span><span class="hl-5">password</span><span class="hl-1">|</span><span class="hl-5">session</span><span class="hl-1"> + </span><span class="hl-5">sshd</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">security</span><span class="hl-1">/</span><span class="hl-5">limits</span><span class="hl-1">.</span><span class="hl-5">conf</span><span class="hl-1"> + </span><span class="hl-5">access</span><span class="hl-1">.</span><span class="hl-5">conf</span><br/><span class="hl-1">│ ├── </span><span class="hl-0">sudoers</span><span class="hl-1"> (</span><span class="hl-8">0o440</span><span class="hl-1">) + </span><span class="hl-5">sudoers</span><span class="hl-1">.</span><span class="hl-5">d</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">systemd</span><span class="hl-1">/</span><span class="hl-5">system</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">debian_version</span><span class="hl-1"> </span><span class="hl-8">12.0</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">fstab</span><span class="hl-1"> </span><span class="hl-7">UUID</span><span class="hl-1"> </span><span class="hl-5">stubs</span><span class="hl-1"> + </span><span class="hl-5">tmpfs</span><span class="hl-1"> </span><span class="hl-5">entries</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">group</span><span class="hl-1"> </span><span class="hl-5">synced</span><span class="hl-1"> </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-5">VirtualUserManager</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">hostname</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">hosts</span><span class="hl-1"> </span><span class="hl-8">127.0</span><span class="hl-1">.</span><span class="hl-8">0.1</span><span class="hl-1"> + ::</span><span class="hl-8">1</span><span class="hl-1"> + </span><span class="hl-7">VM</span><span class="hl-1"> </span><span class="hl-5">hostname</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">issue</span><span class="hl-1"> </span><span class="hl-5">login</span><span class="hl-1"> </span><span class="hl-5">banner</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">locale</span><span class="hl-1">.</span><span class="hl-5">conf</span><span class="hl-1"> </span><span class="hl-7">LANG</span><span class="hl-1">=</span><span class="hl-5">en_US</span><span class="hl-1">.</span><span class="hl-7">UTF</span><span class="hl-1">-</span><span class="hl-8">8</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">localtime</span><span class="hl-1"> / </span><span class="hl-5">timezone</span><span class="hl-1"> </span><span class="hl-7">UTC</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">login</span><span class="hl-1">.</span><span class="hl-5">defs</span><span class="hl-1"> </span><span class="hl-7">UID_MIN</span><span class="hl-1">=</span><span class="hl-8">1000</span><span class="hl-1"> </span><span class="hl-7">SHA512</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">motd</span><span class="hl-1"> </span><span class="hl-5">uses</span><span class="hl-1"> </span><span class="hl-5">ShellProperties</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">os</span><span class="hl-1">-</span><span class="hl-5">release</span><span class="hl-1"> </span><span class="hl-7">NAME</span><span class="hl-1">=</span><span class="hl-2">&quot;Fortune GNU/Linux&quot;</span><span class="hl-1"> + </span><span class="hl-5">ShellProperties</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">passwd</span><span class="hl-1"> </span><span class="hl-5">synced</span><span class="hl-1"> </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-5">VirtualUserManager</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">profile</span><span class="hl-1"> </span><span class="hl-7">PATH</span><span class="hl-1"> + </span><span class="hl-7">PS1</span><span class="hl-1"> </span><span class="hl-5">defaults</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">resolv</span><span class="hl-1">.</span><span class="hl-5">conf</span><span class="hl-1"> </span><span class="hl-8">1.1</span><span class="hl-1">.</span><span class="hl-8">1.1</span><span class="hl-1"> + </span><span class="hl-8">8.8</span><span class="hl-1">.</span><span class="hl-8">8.8</span><br/><span class="hl-1">│ ├── </span><span class="hl-0">shadow</span><span class="hl-1"> (</span><span class="hl-5">mode</span><span class="hl-1"> </span><span class="hl-8">0o640</span><span class="hl-1">, </span><span class="hl-5">fake</span><span class="hl-1"> </span><span class="hl-5">hashes</span><span class="hl-1">)</span><br/><span class="hl-1">│ └── </span><span class="hl-5">shells</span><span class="hl-1"> /</span><span class="hl-5">bin</span><span class="hl-1">/</span><span class="hl-5">sh</span><span class="hl-1"> /</span><span class="hl-5">bin</span><span class="hl-1">/</span><span class="hl-5">bash</span><span class="hl-1"> /</span><span class="hl-5">usr</span><span class="hl-1">/</span><span class="hl-5">bin</span><span class="hl-1">/</span><span class="hl-5">bash</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">home</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">media</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">mnt</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">opt</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">snap</span><span class="hl-1">/</span><span class="hl-5">bin</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-5">srv</span><span class="hl-1">/</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">proc</span><span class="hl-1">/ </span><span class="hl-5">kernel</span><span class="hl-1"> </span><span class="hl-5">simulation</span><span class="hl-1"> </span><span class="hl-0">engine</span><span class="hl-1"> (</span><span class="hl-5">refreshed</span><span class="hl-1"> </span><span class="hl-5">on</span><span class="hl-1"> </span><span class="hl-5">demand</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">boot</span><span class="hl-1">/</span><span class="hl-5">log</span><span class="hl-1"> + </span><span class="hl-5">version</span><span class="hl-1"> </span><span class="hl-5">kernel</span><span class="hl-1"> </span><span class="hl-5">boot</span><span class="hl-1"> </span><span class="hl-5">sequence</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">net</span><span class="hl-1">/</span><span class="hl-5">dev</span><span class="hl-1"> + </span><span class="hl-5">if_inet6</span><span class="hl-1"> + </span><span class="hl-5">tcp</span><span class="hl-1"> + </span><span class="hl-5">tcp6</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">sys</span><span class="hl-1">/</span><span class="hl-5">kernel</span><span class="hl-1">/ </span><span class="hl-5">hostname</span><span class="hl-1">, </span><span class="hl-5">ostype</span><span class="hl-1">, </span><span class="hl-5">osrelease</span><span class="hl-1">, </span><span class="hl-5">pid_max</span><span class="hl-1">,</span><br/><span class="hl-1">│ │ </span><span class="hl-5">threads</span><span class="hl-1">-</span><span class="hl-5">max</span><span class="hl-1">, </span><span class="hl-5">randomize_va_space</span><span class="hl-1">, </span><span class="hl-5">dmesg_restrict</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">sys</span><span class="hl-1">/</span><span class="hl-5">net</span><span class="hl-1">/</span><span class="hl-5">ipv4</span><span class="hl-1">/</span><span class="hl-5">ip_forward</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">sys</span><span class="hl-1">/</span><span class="hl-5">vm</span><span class="hl-1">/</span><span class="hl-5">swappiness</span><span class="hl-1"> + </span><span class="hl-5">overcommit_memory</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">self</span><span class="hl-1">/</span><span class="hl-5">mounts</span><span class="hl-1"> </span><span class="hl-5">mirrors</span><span class="hl-1"> </span><span class="hl-5">most</span><span class="hl-1"> </span><span class="hl-5">recent</span><span class="hl-1"> </span><span class="hl-5">session</span><span class="hl-2">&#39;s /proc/&lt;pid&gt;</span><span class="hl-19">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-8">1</span><span class="hl-1">/ </span><span class="hl-0">init</span><span class="hl-1"> (</span><span class="hl-5">cmdline</span><span class="hl-1">, </span><span class="hl-5">comm</span><span class="hl-1">, </span><span class="hl-5">stat</span><span class="hl-1">, </span><span class="hl-5">status</span><span class="hl-1">, </span><span class="hl-5">environ</span><span class="hl-1">, </span><span class="hl-5">fd</span><span class="hl-1">/, </span><span class="hl-5">fdinfo</span><span class="hl-1">/)</span><br/><span class="hl-1">│ ├── &lt;</span><span class="hl-5">pid</span><span class="hl-1">&gt;/ </span><span class="hl-5">one</span><span class="hl-1"> </span><span class="hl-5">subtree</span><span class="hl-1"> </span><span class="hl-5">per</span><span class="hl-1"> </span><span class="hl-5">active</span><span class="hl-1"> </span><span class="hl-0">session</span><span class="hl-1"> (</span><span class="hl-7">TTY</span><span class="hl-1">-</span><span class="hl-5">derived</span><span class="hl-1"> </span><span class="hl-7">PID</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">cmdline</span><span class="hl-1"> </span><span class="hl-5">kernel</span><span class="hl-1"> </span><span class="hl-5">boot</span><span class="hl-1"> </span><span class="hl-5">args</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">cpuinfo</span><span class="hl-1"> </span><span class="hl-5">real</span><span class="hl-1"> </span><span class="hl-5">host</span><span class="hl-1"> </span><span class="hl-7">CPU</span><span class="hl-1"> </span><span class="hl-5">passthrough</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">filesystems</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">hostname</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">loadavg</span><span class="hl-1"> </span><span class="hl-5">computed</span><span class="hl-1"> </span><span class="hl-5">dynamically</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">meminfo</span><span class="hl-1"> </span><span class="hl-5">real</span><span class="hl-1"> </span><span class="hl-5">host</span><span class="hl-1"> </span><span class="hl-0">memory</span><span class="hl-1"> (</span><span class="hl-5">Total</span><span class="hl-1">/</span><span class="hl-5">Free</span><span class="hl-1">/</span><span class="hl-5">Available</span><span class="hl-1">/</span><span class="hl-5">Buffers</span><span class="hl-1">/</span><span class="hl-5">Cached</span><span class="hl-1">/</span><span class="hl-5">Swap</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">mounts</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">partitions</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">swaps</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">uptime</span><span class="hl-1"> </span><span class="hl-5">computed</span><span class="hl-1"> </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-5">shellStartTime</span><br/><span class="hl-1">│ └── </span><span class="hl-5">version</span><span class="hl-1"> </span><span class="hl-0">Linux</span><span class="hl-1"> &lt;</span><span class="hl-17">kernel</span><span class="hl-1">&gt; (</span><span class="hl-5">fortune</span><span class="hl-1">@</span><span class="hl-5">build</span><span class="hl-1">)</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">root</span><span class="hl-1">/ (</span><span class="hl-5">mode</span><span class="hl-1"> </span><span class="hl-8">0o700</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── .</span><span class="hl-5">bashrc</span><span class="hl-1"> </span><span class="hl-5">colored</span><span class="hl-1"> </span><span class="hl-7">PS1</span><span class="hl-1">, </span><span class="hl-7">PATH</span><span class="hl-1">, </span><span class="hl-5">ll</span><span class="hl-1">/</span><span class="hl-5">la</span><span class="hl-1"> </span><span class="hl-5">aliases</span><br/><span class="hl-1">│ └── .</span><span class="hl-5">profile</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">run</span><span class="hl-1">/ (</span><span class="hl-5">systemd</span><span class="hl-1"> </span><span class="hl-5">tmpfs</span><span class="hl-1"> </span><span class="hl-5">runtime</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">lock</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">systemd</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">user</span><span class="hl-1">/</span><br/><span class="hl-1">│ └── </span><span class="hl-5">utmp</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">sys</span><span class="hl-1">/ </span><span class="hl-5">sysfs</span><span class="hl-1"> </span><span class="hl-5">graph</span><span class="hl-1"> — </span><span class="hl-5">deterministic</span><span class="hl-1">, </span><span class="hl-5">seeded</span><span class="hl-1"> </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-0">hostname</span><span class="hl-1"> (</span><span class="hl-5">fnv1a</span><span class="hl-1">)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">class</span><span class="hl-1">/</span><span class="hl-5">net</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">devices</span><span class="hl-1">/</span><span class="hl-5">virtual</span><span class="hl-1">/</span><span class="hl-5">dmi</span><span class="hl-1">/</span><span class="hl-5">id</span><span class="hl-1">/</span><br/><span class="hl-1">│ │ ├── </span><span class="hl-5">bios_vendor</span><span class="hl-1"> / </span><span class="hl-5">bios_version</span><span class="hl-1"> / </span><span class="hl-5">bios_date</span><br/><span class="hl-1">│ │ ├── </span><span class="hl-5">sys_vendor</span><span class="hl-1"> / </span><span class="hl-5">product_name</span><span class="hl-1"> / </span><span class="hl-5">product_family</span><span class="hl-1"> / </span><span class="hl-5">product_version</span><br/><span class="hl-1">│ │ ├── </span><span class="hl-5">product_uuid</span><span class="hl-1"> / </span><span class="hl-5">product_serial</span><br/><span class="hl-1">│ │ ├── </span><span class="hl-5">chassis_type</span><span class="hl-1"> / </span><span class="hl-5">chassis_vendor</span><span class="hl-1"> / </span><span class="hl-5">chassis_version</span><br/><span class="hl-1">│ │ ├── </span><span class="hl-5">board_name</span><br/><span class="hl-1">│ │ └── </span><span class="hl-5">modalias</span><br/><span class="hl-1">│ └── </span><span class="hl-5">kernel</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">hostname</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">osrelease</span><br/><span class="hl-1">│ └── </span><span class="hl-5">ostype</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">tmp</span><span class="hl-1">/ (</span><span class="hl-5">mode</span><span class="hl-1"> </span><span class="hl-8">0o1777</span><span class="hl-1">, </span><span class="hl-5">sticky</span><span class="hl-1">)</span><br/><span class="hl-1">│</span><br/><span class="hl-1">├── </span><span class="hl-5">usr</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">bin</span><span class="hl-1">/ </span><span class="hl-5">stubs</span><span class="hl-1"> </span><span class="hl-5">for</span><span class="hl-1"> </span><span class="hl-5">all</span><span class="hl-1"> </span><span class="hl-5">built</span><span class="hl-1">-</span><span class="hl-4">in</span><span class="hl-1"> </span><span class="hl-0">commands</span><span class="hl-1"> (</span><span class="hl-5">exec</span><span class="hl-1"> </span><span class="hl-5">builtin</span><span class="hl-1"> &lt;</span><span class="hl-5">name</span><span class="hl-1">&gt;)</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">sbin</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">lib</span><span class="hl-1">/ + </span><span class="hl-5">lib64</span><span class="hl-1">/</span><br/><span class="hl-1">│ ├── </span><span class="hl-5">local</span><span class="hl-1">/</span><span class="hl-5">bin</span><span class="hl-1">|</span><span class="hl-5">lib</span><span class="hl-1">|</span><span class="hl-5">share</span><span class="hl-1">/</span><br/><span class="hl-1">│ └── </span><span class="hl-5">share</span><span class="hl-1">/</span><span class="hl-5">doc</span><span class="hl-1">|</span><span class="hl-5">man</span><span class="hl-1">/</span><span class="hl-5">man1</span><span class="hl-1">/</span><br/><span class="hl-1">│</span><br/><span class="hl-1">└── </span><span class="hl-4">var</span><span class="hl-1">/</span><br/><span class="hl-1"> ├── </span><span class="hl-5">cache</span><span class="hl-1">/</span><span class="hl-5">apt</span><span class="hl-1">/</span><span class="hl-5">archives</span><span class="hl-1">/</span><br/><span class="hl-1"> ├── </span><span class="hl-5">lib</span><span class="hl-1">/</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">apt</span><span class="hl-1">/</span><span class="hl-5">lists</span><span class="hl-1">/</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">misc</span><span class="hl-1">/</span><br/><span class="hl-1"> │ └── </span><span class="hl-5">dpkg</span><span class="hl-1">/</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">available</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">info</span><span class="hl-1">/</span><br/><span class="hl-1"> │ └── </span><span class="hl-5">status</span><span class="hl-1"> </span><span class="hl-5">managed</span><span class="hl-1"> </span><span class="hl-5">by</span><span class="hl-1"> </span><span class="hl-5">VirtualPackageManager</span><br/><span class="hl-1"> ├── </span><span class="hl-5">log</span><span class="hl-1">/</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">apt</span><span class="hl-1">/</span><span class="hl-5">history</span><span class="hl-1">.</span><span class="hl-5">log</span><span class="hl-1"> + </span><span class="hl-5">term</span><span class="hl-1">.</span><span class="hl-5">log</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">auth</span><span class="hl-1">.</span><span class="hl-5">log</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">dpkg</span><span class="hl-1">.</span><span class="hl-5">log</span><br/><span class="hl-1"> │ ├── </span><span class="hl-5">kern</span><span class="hl-1">.</span><span class="hl-5">log</span><br/><span class="hl-1"> │ └── </span><span class="hl-5">syslog</span><br/><span class="hl-1"> ├── </span><span class="hl-5">mail</span><span class="hl-1">/</span><br/><span class="hl-1"> ├── </span><span class="hl-5">run</span><span class="hl-1"> -&gt; /</span><span class="hl-0">run</span><span class="hl-1"> (</span><span class="hl-5">legacy</span><span class="hl-1"> </span><span class="hl-5">symlink</span><span class="hl-1">)</span><br/><span class="hl-1"> ├── </span><span class="hl-5">spool</span><span class="hl-1">/</span><span class="hl-5">cron</span><span class="hl-1">/</span><br/><span class="hl-1"> └── </span><span class="hl-5">tmp</span><span class="hl-1">/</span>
1526
+ </code><button>Copy</button></pre>
1527
+
1528
+ <pre><code class="typescript"><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">refreshProcFs</span><span class="hl-1">(); </span><span class="hl-3">// refresh /proc/* with current system state</span><br/><span class="hl-5">shell</span><span class="hl-1">.</span><span class="hl-0">syncPasswd</span><span class="hl-1">(); </span><span class="hl-3">// sync /etc/passwd|group|shadow from user manager</span>
1529
+ </code><button type="button">Copy</button></pre>
1530
+
1531
+ <h3 id="vfs-path-resolution" class="tsd-anchor-link">VFS PATH Resolution<a href="#vfs-path-resolution" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1532
+ <p>When a command is not a built-in, the shell searches <code>$PATH</code> in the VFS — binaries installed by <code>apt</code> become immediately accessible.</p>
1533
+ <ul>
1534
+ <li><code>/sbin</code> and <code>/usr/sbin</code> are excluded from <code>$PATH</code> for non-root users.</li>
1535
+ <li>Stubs containing <code>exec builtin &lt;name&gt;</code> delegate to the named built-in TS command.</li>
1536
+ </ul>
1537
+ <p><strong>Package-gated commands</strong> (require <code>apt install</code>):</p>
1538
+ <table>
1539
+ <thead>
1540
+ <tr>
1541
+ <th>Command</th>
1542
+ <th>Package</th>
1543
+ </tr>
1544
+ </thead>
1545
+ <tbody>
1546
+ <tr>
1547
+ <td><code>node</code></td>
1548
+ <td><code>nodejs</code></td>
1549
+ </tr>
1550
+ <tr>
1551
+ <td><code>python3</code> / <code>python</code></td>
1552
+ <td><code>python3</code></td>
1553
+ </tr>
1554
+ <tr>
1555
+ <td><code>npm</code> / <code>npx</code></td>
1556
+ <td><code>npm</code></td>
1557
+ </tr>
1558
+ </tbody>
1559
+ </table>
1560
+ <h3 id="built-in-package-registry-25-packages" class="tsd-anchor-link">Built-in Package Registry (25 packages)<a href="#built-in-package-registry-25-packages" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1561
+ <table>
1562
+ <thead>
1563
+ <tr>
1564
+ <th>Package</th>
1565
+ <th>Version</th>
1566
+ <th>Section</th>
1567
+ </tr>
1568
+ </thead>
1569
+ <tbody>
1570
+ <tr>
1571
+ <td><code>vim</code></td>
1572
+ <td>2:9.0.1378-2</td>
1573
+ <td>editors</td>
1574
+ </tr>
1575
+ <tr>
1576
+ <td><code>git</code></td>
1577
+ <td>1:2.39.2-1</td>
1578
+ <td>vcs</td>
1579
+ </tr>
1580
+ <tr>
1581
+ <td><code>python3</code></td>
1582
+ <td>3.11.2-1</td>
1583
+ <td>python</td>
1584
+ </tr>
1585
+ <tr>
1586
+ <td><code>nodejs</code></td>
1587
+ <td>18.19.0</td>
1588
+ <td>javascript</td>
1589
+ </tr>
1590
+ <tr>
1591
+ <td><code>npm</code></td>
1592
+ <td>9.2.0</td>
1593
+ <td>javascript</td>
1594
+ </tr>
1595
+ <tr>
1596
+ <td><code>curl</code></td>
1597
+ <td>7.88.1-10</td>
1598
+ <td>web</td>
1599
+ </tr>
1600
+ <tr>
1601
+ <td><code>wget</code></td>
1602
+ <td>1.21.3-1</td>
1603
+ <td>web</td>
1604
+ </tr>
1605
+ <tr>
1606
+ <td><code>htop</code></td>
1607
+ <td>3.2.2-2</td>
1608
+ <td>utils</td>
1609
+ </tr>
1610
+ <tr>
1611
+ <td><code>openssh-client</code></td>
1612
+ <td>1:9.2p1-2</td>
1613
+ <td>net</td>
1614
+ </tr>
1615
+ <tr>
1616
+ <td><code>openssh-server</code></td>
1617
+ <td>1:9.2p1-2</td>
1618
+ <td>net</td>
1619
+ </tr>
1620
+ <tr>
1621
+ <td><code>net-tools</code></td>
1622
+ <td>2.10-0.1</td>
1623
+ <td>net</td>
1624
+ </tr>
1625
+ <tr>
1626
+ <td><code>iputils-ping</code></td>
1627
+ <td>3:20221126-1</td>
1628
+ <td>net</td>
1629
+ </tr>
1630
+ <tr>
1631
+ <td><code>jq</code></td>
1632
+ <td>1.6-2.1</td>
1633
+ <td>utils</td>
1634
+ </tr>
1635
+ <tr>
1636
+ <td><code>build-essential</code></td>
1637
+ <td>12.9</td>
1638
+ <td>devel</td>
1639
+ </tr>
1640
+ <tr>
1641
+ <td><code>gcc</code></td>
1642
+ <td>4:12.2.0-3</td>
1643
+ <td>devel</td>
1644
+ </tr>
1645
+ <tr>
1646
+ <td><code>g++</code></td>
1647
+ <td>4:12.2.0-3</td>
1648
+ <td>devel</td>
1649
+ </tr>
1650
+ <tr>
1651
+ <td><code>make</code></td>
1652
+ <td>4.3-4.1</td>
1653
+ <td>devel</td>
1654
+ </tr>
1655
+ <tr>
1656
+ <td><code>less</code></td>
1657
+ <td>590-2</td>
1658
+ <td>text</td>
1659
+ </tr>
1660
+ <tr>
1661
+ <td><code>unzip</code></td>
1662
+ <td>6.0-28</td>
1663
+ <td>utils</td>
1664
+ </tr>
1665
+ <tr>
1666
+ <td><code>rsync</code></td>
1667
+ <td>3.2.7-1</td>
1668
+ <td>net</td>
1669
+ </tr>
1670
+ <tr>
1671
+ <td><code>tmux</code></td>
1672
+ <td>3.3a-3</td>
1673
+ <td>utils</td>
1674
+ </tr>
1675
+ <tr>
1676
+ <td><code>tree</code></td>
1677
+ <td>2.1.0-1</td>
1678
+ <td>utils</td>
1679
+ </tr>
1680
+ <tr>
1681
+ <td><code>ca-certificates</code></td>
1682
+ <td>20230311</td>
1683
+ <td>misc</td>
1684
+ </tr>
1685
+ <tr>
1686
+ <td><code>sudo</code></td>
1687
+ <td>1.9.13p3-1</td>
1688
+ <td>admin</td>
1689
+ </tr>
1690
+ <tr>
1691
+ <td><code>systemd</code></td>
1692
+ <td>252.22-1</td>
1693
+ <td>admin</td>
1694
+ </tr>
1695
+ </tbody>
1696
+ </table>
1697
+ </details>
1698
+ <hr>
1699
+ <details>
1700
+ <summary><strong>Configuration</strong></summary>
1701
+ <h3 id="environment-variables" class="tsd-anchor-link">Environment Variables<a href="#environment-variables" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1702
+ <table>
1703
+ <thead>
1704
+ <tr>
1705
+ <th>Variable</th>
1706
+ <th>Default</th>
1707
+ <th>Description</th>
1708
+ </tr>
1709
+ </thead>
1710
+ <tbody>
1711
+ <tr>
1712
+ <td><code>SSH_MIMIC_FAST_PASSWORD_HASH</code></td>
1713
+ <td><code>&quot;&quot;</code></td>
1714
+ <td>Use SHA-256 instead of scrypt (dev only). Set to <code>1</code> or <code>true</code>.</td>
1715
+ </tr>
1716
+ <tr>
1717
+ <td><code>SSH_MIMIC_AUTO_SUDO_NEW_USERS</code></td>
1718
+ <td><code>&quot;true&quot;</code></td>
1719
+ <td>Auto-grant sudo to new users. Set to <code>0</code>, <code>false</code>, <code>no</code>, or <code>off</code> to disable.</td>
1720
+ </tr>
1721
+ <tr>
1722
+ <td><code>DEV_MODE</code></td>
1723
+ <td><code>&quot;&quot;</code></td>
1724
+ <td>Enable performance logging.</td>
1725
+ </tr>
1726
+ <tr>
1727
+ <td><code>RENDER_PERF</code></td>
1728
+ <td><code>&quot;&quot;</code></td>
1729
+ <td>Enable render performance logging.</td>
1730
+ </tr>
1731
+ </tbody>
1732
+ </table>
1733
+ <h3 id="constructor-options" class="tsd-anchor-link">Constructor Options<a href="#constructor-options" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
1734
+ <pre><code class="typescript"><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualShell</span><span class="hl-1">(</span><span class="hl-5">hostname</span><span class="hl-1">, </span><span class="hl-5">properties</span><span class="hl-1">?, </span><span class="hl-5">vfsOptions</span><span class="hl-1">?)</span><br/><span class="hl-3">// vfsOptions: { mode: &quot;memory&quot;|&quot;fs&quot;, snapshotPath?: string }</span><br/><br/><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSshServer</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-5">port</span><span class="hl-1">, hostname?,</span><br/><span class="hl-1"> shell?,</span><br/><span class="hl-1"> maxAuthAttempts?, </span><span class="hl-3">// default: 5</span><br/><span class="hl-1"> lockoutDurationMs?, </span><span class="hl-3">// default: 60_000</span><br/><span class="hl-1">})</span><br/><br/><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-0">VirtualSftpServer</span><span class="hl-1">({ </span><span class="hl-5">port</span><span class="hl-1">, hostname?, shell? })</span><br/><span class="hl-3">// or: { port, vfs, users } without a shell instance</span>
1735
+ </code><button type="button">Copy</button></pre>
1736
+
1737
+ </details>
1738
+ <hr>
1739
+ <details>
1740
+ <summary><strong>Performance &amp; Scalability</strong></summary>
1741
+ <pre><code class="bash"><span class="hl-0">bun</span><span class="hl-1"> </span><span class="hl-2">./benchmark-virtualshell.ts</span>
1742
+ </code><button type="button">Copy</button></pre>
1743
+
1744
+ <p>Reports shell initialization time, command execution time, and RSS memory by concurrency. Designed to scale to <strong>1000+ parallel environments</strong>.</p>
1745
+ <ul>
1746
+ <li>SSH server is event-driven — handles many concurrent connections.</li>
1747
+ <li><code>SshClient</code> is sequential per instance — create multiple for parallel operations.</li>
1748
+ <li>Each <code>VirtualShell</code> is fully independent.</li>
1749
+ </ul>
1750
+ <p><strong>Tips:</strong></p>
1751
+ <ul>
1752
+ <li>Use <code>SSH_MIMIC_FAST_PASSWORD_HASH=1</code> in tests to skip scrypt overhead.</li>
1753
+ <li>Reuse long-lived shell instances for low-latency command bursts.</li>
1754
+ </ul>
1755
+ </details>
1756
+ <hr>
1757
+ <details>
1758
+ <summary><strong>Types &amp; TypeScript</strong></summary>
1759
+ <pre><code class="typescript"><span class="hl-6">import</span><span class="hl-1"> </span><span class="hl-6">type</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-5">VfsOptions</span><span class="hl-1">, </span><span class="hl-5">VfsPersistenceMode</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">VfsSnapshot</span><span class="hl-1">, </span><span class="hl-5">VfsNodeStats</span><span class="hl-1">, </span><span class="hl-5">VfsFileNode</span><span class="hl-1">, </span><span class="hl-5">VfsDirectoryNode</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">WriteFileOptions</span><span class="hl-1">, </span><span class="hl-5">RemoveOptions</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">CommandContext</span><span class="hl-1">, </span><span class="hl-5">CommandResult</span><span class="hl-1">, </span><span class="hl-5">CommandMode</span><span class="hl-1">, </span><span class="hl-5">CommandOutcome</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">ShellModule</span><span class="hl-1">, </span><span class="hl-5">ShellEnv</span><span class="hl-1">, </span><span class="hl-5">SudoChallenge</span><span class="hl-1">, </span><span class="hl-5">NanoEditorSession</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">AuditLogEntry</span><span class="hl-1">, </span><span class="hl-5">HoneyPotStats</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">ShellStream</span><span class="hl-1">, </span><span class="hl-5">ExecStream</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-6">from</span><span class="hl-1"> </span><span class="hl-2">&quot;typescript-virtual-container&quot;</span><span class="hl-1">;</span>
1760
+ </code><button type="button">Copy</button></pre>
1761
+
1762
+ </details>
1763
+ <hr>
1764
+ <h2 id="troubleshooting" class="tsd-anchor-link">Troubleshooting<a href="#troubleshooting" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1765
+ <p><strong><code>Error: listen EADDRINUSE :::2222</code></strong> — port already in use. Change port or stop existing process.</p>
1766
+ <p><strong>Auth always fails</strong> — root has no password by default. Verify with <code>users.verifyPassword(username, password)</code>. Check lockout: <code>ssh.clearLockout(ip)</code>.</p>
1767
+ <p><strong><code>Command 'xyz' not found</code> (exit 127)</strong> — not a registered built-in and not found in VFS <code>$PATH</code>. Register with <code>shell.addCommand()</code> or <code>apt install</code> the package.</p>
1768
+ <p><strong>Shell scripting — <code>if</code> block not working</strong> — ensure each keyword is on its own line or separated by <code>;</code>.</p>
1769
+ <p><strong><code>snapshotPath</code> required error</strong> — set <code>mode: &quot;fs&quot;</code> without <code>snapshotPath</code>: <code>new VirtualFileSystem({ mode: &quot;fs&quot;, snapshotPath: &quot;./data&quot; })</code>.</p>
1770
+ <p><strong>Variables not persisting between <code>exec()</code> calls</strong> — <code>SshClient</code> shares one <code>ShellEnv</code> per shell instance. <code>export</code> in one call is visible in the next. For isolation, create a new <code>SshClient</code>.</p>
1771
+ <p><strong><code>Too many levels of symbolic links</code></strong> — symlink chain exceeds 8 hops. Check for circular links or increase <code>maxDepth</code> in <code>resolveSymlink()</code>.</p>
1772
+ <hr>
1773
+ <h2 id="faq" class="tsd-anchor-link">FAQ<a href="#faq" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1774
+ <p><strong>Is this a real container runtime?</strong>
1775
+ No — it emulates SSH sessions, users, and filesystem behavior in a virtual runtime. Ideal for testing, simulations, and automation where full OS isolation is not required.</p>
1776
+ <p><strong>Can I use this in production?</strong>
1777
+ Yes for automation contexts (sandboxed command runners, test harnesses, training environments, honeypots). It is not a security boundary like a real container/VM.</p>
1778
+ <p><strong>Does the VFS touch the host filesystem?</strong>
1779
+ In <code>&quot;memory&quot;</code> mode: no. In <code>&quot;fs&quot;</code> mode: one binary file (<code>vfs-snapshot.vfsb</code>) inside <code>snapshotPath</code> only.</p>
1780
+ <p><strong>Can I run multiple isolated shells?</strong>
1781
+ Yes. Each <code>new VirtualShell(...)</code> is completely independent (separate VFS, users, env state).</p>
1782
+ <p><strong>Does the shell support <code>&amp;&amp;</code>, <code>||</code>, and <code>;</code>?</strong>
1783
+ Yes — plus pipes, redirections, <code>if</code>/<code>for</code>/<code>while</code>/<code>case</code>, and function definitions.</p>
1784
+ <p><strong>Can I use this for honeypot deployments?</strong>
1785
+ Yes — use <code>HoneyPot.attach()</code> to capture all activity, configure <code>maxAuthAttempts</code> to throttle scanners, export on shutdown.</p>
1786
+ <p><strong>Is SFTP fully supported?</strong>
1787
+ Core operations are implemented. Extended attributes and symlinks return <code>OP_UNSUPPORTED</code>.</p>
1788
+ <hr>
1789
+ <h2 id="contributing" class="tsd-anchor-link">Contributing<a href="#contributing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1790
+ <ol>
1791
+ <li>Fork and create a feature branch: <code>git checkout -b feat/my-feature</code></li>
1792
+ <li>Add changes and tests.</li>
1793
+ <li>Format and lint: <code>bun format &amp;&amp; bun check</code></li>
1794
+ <li>Push and open a PR.</li>
1795
+ </ol>
1796
+ <p><strong>Standards:</strong> Biome formatting · full TypeScript (no <code>any</code>) · ✅ <strong>JSDoc on all built-in commands</strong> · async/await · <code>description</code> and <code>category</code> fields on new <code>ShellModule</code> · unit tests (prioritized for core features; advanced tests planned).</p>
1797
+ <hr>
1798
+ <h2 id="security" class="tsd-anchor-link">Security<a href="#security" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1799
+ <ul>
1800
+ <li>Passwords hashed with scrypt (N=32768, r=8, p=1) with random per-user salt.</li>
1801
+ <li>Root account always exists and cannot be deleted.</li>
1802
+ <li>Per-IP rate limiting prevents automated brute-force on the SSH server.</li>
1803
+ <li>This project does <strong>not</strong> provide kernel-level or process-level isolation.</li>
1804
+ <li>Do <strong>not</strong> expose to the public internet without understanding the risks.</li>
1805
+ </ul>
1806
+ <p>Vulnerability reports: contact maintainers privately before public disclosure — see <code>SECURITY.md</code>.</p>
1807
+ <hr>
1808
+ <h2 id="compatibility" class="tsd-anchor-link">Compatibility<a href="#compatibility" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1809
+ <ul>
1810
+ <li><strong>Node.js</strong>: <code>&gt;=18</code> · <strong>Bun</strong>: Supported · <strong>TypeScript</strong>: <code>&gt;=5.0</code></li>
1811
+ <li><strong>OS</strong>: Linux, macOS, Windows (via Node/Bun)</li>
1812
+ </ul>
1813
+ <hr>
1814
+ <h2 id="license" class="tsd-anchor-link">License<a href="#license" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1815
+ <p>MIT — see <a href="media/LICENSE">LICENSE</a>.</p>
1816
+ <hr>
1817
+ <h2 id="roadmap" class="tsd-anchor-link">Roadmap<a href="#roadmap" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
1818
+ <p>Open:</p>
1819
+ <ul>
1820
+ <li>[ ] WebSocket-based remote shell client (experimental)</li>
1821
+ </ul>
1822
+ <details>
1823
+ <summary>Completed</summary>
1824
+ <ul>
1825
+ <li>[x] Custom command plugin API · per-user quotas · SSH public-key auth · per-IP rate limiting</li>
1826
+ <li>[x] Pure in-memory VFS · symlinks · binary snapshot format (VFSB, ~27% smaller than JSON+base64)</li>
1827
+ <li>[x] Linux rootfs on boot — <code>/etc</code>, <code>/proc</code>, <code>/sys</code>, <code>/dev</code>, <code>/usr</code>, <code>/var</code></li>
1828
+ <li>[x] Virtual package manager — <code>apt</code>/<code>dpkg</code>, 25 packages, VFS file writes</li>
1829
+ <li>[x] 92 built-in commands across 9 categories (<code>seq</code> added)</li>
1830
+ <li>[x] Real shell interpreter — <code>if</code>/<code>for</code>/<code>while</code>/<code>case</code>/functions, <code>$(cmd)</code>, <code>$((expr))</code>, <code>${#VAR}</code>, <code>{a,b,c}</code> brace expansion, <code>{1..N}</code> ranges, <code>2&gt;/dev/null</code> stderr redirect, <code>2&gt;&amp;1</code>, <code>(( x++ ))</code></li>
1831
+ <li>[x] <code>curl</code>/<code>wget</code> as pure <code>fetch()</code> · VFS PATH resolution · <code>/sbin</code> root-only</li>
1832
+ <li>[x] <code>/proc/self</code> and <code>/proc/&lt;pid&gt;</code> per-session entries</li>
1833
+ <li>[x] Snapshot diff tooling — <code>diffSnapshots</code>, <code>formatDiff</code>, <code>assertDiff</code></li>
1834
+ <li>[x] <code>node</code>/<code>python3</code>/<code>npm</code>/<code>npx</code> — package-gated virtual REPL stubs</li>
1835
+ <li>[x] Web shell bundles (<code>web.min.js</code>, <code>web-full-api.min.js</code>) — fully browser-native with IndexedDB VFS</li>
1836
+ <li>[x] Self-standalone CLI (<code>self-standalone.js</code>) — single-file interactive shell, per-user history, tab completion</li>
1837
+ <li>[x] 120+ <code>man</code> pages — all built-in commands documented via <code>man &lt;cmd&gt;</code></li>
1838
+ <li>[x] Shared <code>tokenize.ts</code> — unified tokenizer for shell parser and runtime (eliminates duplication)</li>
1839
+ <li>[x] <code>PasswordChallenge</code> type — generic interactive password flow for <code>adduser</code>, <code>passwd</code>, <code>deluser</code></li>
1840
+ <li>[x] <code>VirtualFileSystem.mount(vPath, hostPath, { readOnly })</code> — bind-mount host directories into the VM; read-only by default; browser-safe (silent no-op)</li>
1841
+ </ul>
1842
+ </details></div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#_"><span></span></a><ul><li><a href="#table-of-contents"><span>Table of <wbr/>Contents</span></a></li><li><a href="#three-ways-to-run"><span>Three ways to run</span></a></li><li><a href="#get-started"><span>Get <wbr/>Started</span></a></li><li><ul><li><a href="#install"><span>Install</span></a></li><li><a href="#try-instantly-zero-install"><span>Try instantly (zero install)</span></a></li><li><a href="#ssh-server"><span>SSH server</span></a></li><li><a href="#web-shell-browser"><span>Web shell (browser)</span></a></li><li><a href="#programmatic-api"><span>Programmatic <wbr/>API</span></a></li></ul></li><li><a href="#how-it-works"><span>How <wbr/>It <wbr/>Works</span></a></li><li><ul><li><a href="#_-1"><span></span></a></li><li><a href="#_-2"><span></span></a></li><li><a href="#_-3"><span></span></a></li><li><a href="#_-4"><span></span></a></li><li><ul><li><a href="#mount-api"><span>Mount <wbr/>API</span></a></li><li><a href="#vfsb-binary-format"><span>VFSB <wbr/>Binary <wbr/>Format</span></a></li></ul></li><li><a href="#_-5"><span></span></a></li><li><a href="#_-6"><span></span></a></li><li><a href="#snapshot-diff-tooling"><span>Snapshot <wbr/>Diff <wbr/>Tooling</span></a></li><li><a href="#_-7"><span></span></a></li><li><a href="#programmatic-api-1"><span> (<wbr/>Programmatic <wbr/>API)</span></a></li><li><a href="#key-types"><span>Key <wbr/>Types</span></a></li><li><a href="#command-helpers"><span>Command <wbr/>Helpers</span></a></li><li><a href="#ssh-server-with-events"><span>SSH <wbr/>Server with <wbr/>Events</span></a></li><li><a href="#ssh-sftp-with-shared-state"><span>SSH + <wbr/>SFTP with <wbr/>Shared <wbr/>State</span></a></li><li><a href="#multi-user-environment-with-quotas"><span>Multi-<wbr/>User <wbr/>Environment with <wbr/>Quotas</span></a></li><li><a href="#persistent-state"><span>Persistent <wbr/>State</span></a></li><li><a href="#public-key-authentication"><span>Public-<wbr/>Key <wbr/>Authentication</span></a></li><li><a href="#rate-limiting"><span>Rate <wbr/>Limiting</span></a></li><li><a href="#shell-operators-and-variables"><span>Shell <wbr/>Operators and <wbr/>Variables</span></a></li><li><a href="#shell-scripting"><span>Shell <wbr/>Scripting</span></a></li><li><a href="#snapshot-based-test-fixtures"><span>Snapshot-<wbr/>Based <wbr/>Test <wbr/>Fixtures</span></a></li><li><a href="#snapshot-diff-in-tests"><span>Snapshot <wbr/>Diff in <wbr/>Tests</span></a></li><li><a href="#symlinks"><span>Symlinks</span></a></li><li><a href="#security-auditing-with-honeypot"><span>Security <wbr/>Auditing with <wbr/>Honey<wbr/>Pot</span></a></li><li><a href="#concurrent-clients"><span>Concurrent <wbr/>Clients</span></a></li><li><a href="#bashrc"><span>.bashrc</span></a></li><li><a href="#navigation"><span>Navigation</span></a></li><li><a href="#files-filesystem"><span>Files &amp; <wbr/>Filesystem</span></a></li><li><a href="#text-processing"><span>Text <wbr/>Processing</span></a></li><li><a href="#archive-compression"><span>Archive &amp; <wbr/>Compression</span></a></li><li><a href="#system"><span>System</span></a></li><li><a href="#network"><span>Network</span></a></li><li><a href="#shell-scripting-1"><span>Shell &amp; <wbr/>Scripting</span></a></li><li><a href="#package-management"><span>Package <wbr/>Management</span></a></li><li><a href="#users-permissions"><span>Users &amp; <wbr/>Permissions</span></a></li><li><a href="#operators-and-redirections"><span>Operators and <wbr/>Redirections</span></a></li><li><a href="#variable-expansion"><span>Variable <wbr/>Expansion</span></a></li><li><a href="#arithmetic"><span>Arithmetic</span></a></li><li><a href="#conditionals"><span>Conditionals</span></a></li><li><a href="#loops"><span>Loops</span></a></li><li><a href="#functions-and-case"><span>Functions and case</span></a></li><li><a href="#script-files"><span>Script <wbr/>Files</span></a></li><li><a href="#bashrc-1"><span>.bashrc</span></a></li><li><a href="#directory-layout"><span>Directory <wbr/>Layout</span></a></li><li><a href="#vfs-path-resolution"><span>VFS <wbr/>PATH <wbr/>Resolution</span></a></li><li><a href="#built-in-package-registry-25-packages"><span>Built-<wbr/>in <wbr/>Package <wbr/>Registry (25 packages)</span></a></li><li><a href="#environment-variables"><span>Environment <wbr/>Variables</span></a></li><li><a href="#constructor-options"><span>Constructor <wbr/>Options</span></a></li></ul></li><li><a href="#troubleshooting"><span>Troubleshooting</span></a></li><li><a href="#faq"><span>FAQ</span></a></li><li><a href="#contributing"><span>Contributing</span></a></li><li><a href="#security"><span>Security</span></a></li><li><a href="#compatibility"><span>Compatibility</span></a></li><li><a href="#license"><span>License</span></a></li><li><a href="#roadmap"><span>Roadmap</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">typescript-virtual-container</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>