iTranslated by AI
Building a terminal to manipulate local files from the browser
As part of my Golden Week activities as a "frontend development should be completed within the frontend" extremist, I created a prototype for a terminal that reads and writes local files in the browser.
Here is a view of mounting and manipulating local files.

Source code
How it works
- Implement FS API using the File System Access API
- Implement several Unix-like commands on xterm.js that interact with the FS
- Pass the contents of
open <file>to Monaco Editor, and write the content saved via Cmd-S back to the FS
The initial storage opened is the temporary storage from navigator.storage.getDirectory(), which is volatile depending on the browser's state (as specified in the documentation). The main intended use is to use mount to operate on local files.
Since the File System Access API is currently only supported by Chrome, it only works in Chrome.
Basic Usage
Unix-like commands such as cd, ls, cp, mkdir, and rm have been implemented. Tab completion works for items within the same directory. I'll implement deep path completion when I feel like it.
Items not yet implemented: Pipe processing like |, >, and *, standard I/O, and glob pattern enumeration are currently in progress.
WebShell-Specific Commands
- The
mountcommand mounts a specified directory to/<dirname>. - The
open <file>command allows for editing within the built-in editor. - The
bundle <file>command builds a specified file using Rollup. This is also reflected in the local file system. - The
exec <file>command bundles and executes a file on a Web Worker. It also supports TypeScript.
Here is a sample:
# demo bundle on temporal storage
/workspace
# run
$ exec main.ts
# bundle to ./dist
$ bundle main.ts
gen > /workspace/dist/main.js
$ mount
# choose your local directory
# ...now I choose fs-test directory
/fs-test
# create empty file
$ touch test
$ ls
test
# open file on left editor(here)
$ open main.ts
# edit and (Ctrl or Cmd)+S
$ ls
test
main.ts
$ bundle main.ts
> gen > /fs-test/dist/main.ts
Future Plans
Since there's no sign of WebContainers becoming open-source, I decided to build something based on the same concept myself.
Actually, I built this while deciphering https://wasi.rreverser.com/. That project runs WASI-built coreutils and connects I/O to WASI, whereas web-shell is just a "fake" that looks similar. I've implemented the mechanism for standard I/O, but I haven't yet built the mechanism for piping...
I actually started this to study WASI, and I intend to connect it to a WASI adapter from here. My goal is to make it so that commands written in Rust can run. Also, I wanted to create a place where I could try out hand-written WebAssembly text format.
The novelty at this point is probably the integration of Monaco Editor with the open command. Additionally, for things like Rollup + TS + Terser that naturally run on the web, I've implemented them directly as commands.
The significance for me is that by building it from scratch and understanding the architecture, it has become a foundation that I can expand in any way I want.
Discussion