Skip to content

Local Files

Terminality includes a Rust-native local file manager as a first-class Pane type. The WebView never touches the filesystem directly.

Safety by Design

File operations are descriptor-relative and generation-scoped:

  • Every path must be absolute, normalized, and within a registered root capability.
  • Directory components are opened with no-follow semantics — a swapped symlink cannot redirect traversal.
  • Mutating actions accept only (generation, index) references from the current listing — never caller-supplied paths.
  • Batches are non-empty, duplicate-free, and bounded to 100 entries.

Identity Verification

Each cached entry carries a native sidecar: Unix (device, inode) or Windows (volume, file index). The core re-verifies through the retained parent capability three times: before confirmation, after confirmation, and immediately before each side effect.

A same-name, same-kind replacement fails stale instead of inheriting consent.

Features

  • Navigation: breadcrumb, parent, home. Platform roots (/ on Unix, logical volumes on Windows).
  • Large directories: paged rendering with hard entry limit.
  • Multi-selection: generation-scoped, survives directory navigation within the same generation.
  • Create / Rename: single filename component, atomic no-replace rename primitive — concurrent destination cannot be silently overwritten.
  • Trash-only delete: macOS Trash, Windows Recycle Bin (with undo record), or Ubuntu trash portal / gio trash.
    • Bounded, expiring, single-use prepare token freezes selections.
    • Native platform adapter forces localized confirmation before the first side effect.
    • No permanent-delete fallback. No automatic retry after indeterminate result.
  • Native reveal: open in platform file manager.

What React Receives

The filesystem plugin is intentionally not granted to the WebView. React receives:

  • Display/navigation paths for breadcrumbs and directory rendering.
  • Bounded metadata snapshots (name, kind, size, modified).
  • Typed commands: navigateTo, goToParent, goToHome, activate, create, rename, trash, reveal.

Non-UTF-8 names are skipped and counted — never lossily converted into operable paths. Native errors cross as a small stable vocabulary; raw filesystem diagnostics are never logged or returned.

Architecture

React FilePane Component
  → FileServiceViewModel (binding)
  → FileService (Rust)
  → openat2 / CreateFile2 (platform adapter)

PaneId remains stable. Replacing the Pane's content rotates PaneContentId, which invalidates its child ViewModel and owned directory snapshots — stale async results cannot publish into a new Pane generation.

Terminality — Connect Everycorner