summaryrefslogtreecommitdiff
path: root/docs/fs.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/fs.md')
-rw-r--r--docs/fs.md89
1 files changed, 89 insertions, 0 deletions
diff --git a/docs/fs.md b/docs/fs.md
new file mode 100644
index 00000000..8805ffde
--- /dev/null
+++ b/docs/fs.md
@@ -0,0 +1,89 @@
+# Filesystem
+
+Every native session serves 9P2000 on a Unix socket. Pane shells receive
+`PARDES_9P` (socket path) and `PARDES_PANE` (pane serial). The socket is
+`$XDG_RUNTIME_DIR/pardes-9p-<pid>.sock`, or lives under
+`~/.local/state/pardes` when XDG_RUNTIME_DIR is unset. Detached sessions use
+their session name; `--9p=<name>` overrides it.
+
+A `pardes <file>` launched from a pane forwards Look to that pane over 9P.
+`--nested` opens a separate editor and disables forwarding from its pane shells;
+its 9P service stays available.
+
+Look resolves the OS filesystem first, then the editor's virtual filesystem.
+Explicit paths bypass that search:
+
+| Editor path | Meaning | 9P server path |
+|---|---|---|
+| `/n/os/proc/self` | OS filesystem | `/os/proc/self` |
+| `/n/self/pane/2/body` | pane 2's text | `/self/pane/2/body` |
+| `/virtual/src/pardes.zig` | source embedded in this build | `/self/src/pardes.zig` |
+| `/n/peer/self/pane/2/body` | another session's text | peer's `/self/pane/2/body` |
+
+`--mount=peer=work` mounts the named session `work`; the dial can also be an
+absolute socket path, `unix!/path`, `tcp!IP!port`, or `quic!IP!port`.
+At runtime, use `Mount peer dial` and
+`Unmount peer`. There are eight named mounts; `os` and `self` are reserved.
+Unmount refuses mounts still used by a pane, its working directory, or a
+pending Save. Mounts are saved in dumps. Save uses the file's original mount.
+
+`pardes --9p-tcp='tcp!127.0.0.1!5640'` adds a TCP listener alongside the Unix
+socket. Build with `-Dquic=true` and system OpenSSL 3.6+ to enable QUIC;
+`--9p-quic='quic!127.0.0.1!5641'` adds its listener. Both accept numeric
+IPv4/IPv6 addresses, not DNS names. Listener port zero chooses a free port;
+`/self/listeners` reports all active dial addresses.
+
+All connections have session access, including `os`. TCP is unencrypted.
+QUIC uses an ephemeral TLS identity without peer verification or login.
+It carries 9P2000 on one bidirectional stream with ALPN `pardes-9p`.
+The four application connection slots are shared across transports;
+OpenSSL's internal buffers are separate, dynamically allocated memory.
+
+[Plan9port's client](https://9fans.github.io/plan9port/man/man1/9p.html) can
+drive Unix or TCP without a kernel mount:
+
+```sh
+9p -n -a "unix!$PARDES_9P" read self/index
+9p -n -a 'tcp!127.0.0.1!5640' read self/index
+```
+
+For [Linux v9fs](https://www.kernel.org/doc/html/latest/filesystems/9p.html),
+use `version=9p2000,cache=none,access=any` and `trans=unix`, or `trans=tcp`
+with `port=5640`. Set `uname`, `dfltuid`, and `dfltgid` for the local user.
+Leave `aname` empty: the mount root contains `os` and `self`. Kernel mounts
+are not part of the test suite. Neither 9P2000.u nor 9P2000.L is implemented.
+Existing Plan9port/v9fs clients need a userspace bridge for QUIC.
+
+The server root contains `os` and `self`. Under `self`, `index` lists panes,
+`new/ctl` creates a pane and returns its serial, and `pane/<serial>` contains
+`body`, `tag`, `ctl`, `addr`, `data`, `event`, and selection files. Terminal
+panes additionally have `pty/{ctl,status,data}`.
+
+`EffectCode <effect>` lists the current backend's embedded implementation
+files under `/virtual`; Look opens their full source.
+
+`self/screen` returns JSON with `cols`, `rows`, `cursor`, a `styles` table,
+and row-major `cells` of `[grapheme, style_index]`. Each open freezes one
+frame until close, including across multiple reads. The independent client
+can inspect it directly with `Client(socket_path).screen()`.
+
+A terminal `body` freezes its history on the first read of each open handle;
+later reads use the same bytes while output continues. Close and reopen for
+newer history, or read `pty/data` for the live stream. Screen and terminal-body
+snapshots share 32 handle slots, released on close or disconnect.
+
+Writing `body` appends; opening it with truncation replaces its contents.
+`addr` selects a range and `data` replaces that range. `ctl` accepts `name`,
+`look <word>`, `get`, `put`, `del`, and `delete`. Look resolves from that pane
+without editing its body or tag. Holding `event` open redirects the pane's Look
+and Exec clicks to that client; writing a record back performs the action.
+
+This is a control filesystem, not a complete POSIX export. Native filenames
+may contain up to 255 bytes. Existing regular OS files support read, write,
+and truncation to zero; protocol create, remove, rename, and other metadata
+changes are refused. Ownership, permissions, and timestamps are synthetic.
+
+`zig build fs-test` drives real sessions using the independent Python client
+in `test/ninep.py`. `zig build 9p-test` checks the freestanding wire protocol;
+`zig build fs-bench` measures filesystem transactions in the core.
+`zig build fs-test quic-test -Dquic=true` also exercises QUIC mounts and I/O.