> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/sxyazi/yazi/llms.txt
> Use this file to discover all available pages before exploring further.

# Virtual Filesystem (VFS)

> Remote file management with SFTP and extensible provider system

Yazi includes a Virtual Filesystem (VFS) that abstracts file operations across different storage backends. This enables seamless remote file management alongside local files using the same interface.

## Overview

The VFS provides a unified API for file operations regardless of the underlying storage:

* **Local files** - Standard filesystem operations
* **SFTP** - SSH-based remote file access
* **Archive files** - Navigate inside archives (future)
* **Custom providers** - Extensible for new backends

## Architecture

The VFS is implemented through a provider system in `yazi-vfs/`:

```rust theme={null}
pub trait Provider {
    type File;
    type Gate;
    type ReadDir;
    type UrlCow;

    async fn absolute(&self) -> io::Result<Self::UrlCow>;
    async fn canonicalize(&self) -> io::Result<UrlBuf>;
    async fn copy<P>(&self, to: P, attrs: Attrs) -> io::Result<u64>;
    async fn create(&self) -> io::Result<RwFile>;
    async fn metadata(&self) -> io::Result<Cha>;
    async fn read_dir(self) -> io::Result<Self::ReadDir>;
    async fn remove_file(&self) -> io::Result<()>;
    async fn rename<P>(&self, to: P) -> io::Result<()>;
    // ... and more
}
```

## URL Scheme

Yazi uses URL-based paths to identify resources:

```rust theme={null}
pub enum Url<'a> {
    Regular(&'a Path),           // Local: /home/user/file.txt
    Search { .. },               // Search: fzf://query
    Archive { .. },              // Archive: file.zip!/internal/path
    Sftp { loc, domain },        // SFTP: sftp://hostname/path
}
```

### Example URLs

* Local: `/home/user/documents/file.txt`
* SFTP: `sftp://server.example.com/var/www/`
* Archive: `/home/user/archive.zip!/folder/file.txt` (future)
* Search: `fzf://search-query`

## SFTP Support

Yazi provides full SFTP support for remote file management over SSH.

### Configuration

Configure SFTP hosts in `~/.config/yazi/yazi.toml`:

```toml theme={null}
[[vfs.sftp]]
name = "production"
host = "server.example.com"
port = 22
user = "username"
# Authentication via SSH agent or key file

[[vfs.sftp]]
name = "staging"
host = "192.168.1.100"
port = 2222
user = "deploy"
```

### Connecting

Connect to SFTP servers using the `cd` command:

```bash theme={null}
# In Yazi, press : to enter command mode
cd sftp://production/var/www
cd sftp://staging/home/deploy
```

Yazi will:

1. Authenticate via SSH agent or key file
2. Establish SFTP connection
3. Navigate to the specified path
4. Display remote files like local ones

### Connection Management

SFTP connections are pooled and reused for efficiency:

```rust theme={null}
impl<'a> Sftp<'a> {
    pub(super) async fn op(&self) -> io::Result<deadpool::managed::Object<Conn>> {
        Conn { name: self.name, config: self.config }.roll().await
    }
}
```

Connections are:

* **Persistent** - Reused across operations
* **Automatic reconnect** - Handle network interruptions
* **Concurrent** - Multiple operations use same connection
* **Pooled** - Connection pool prevents resource exhaustion

### Supported Operations

All standard file operations work over SFTP:

#### Reading

* List directories
* Read file contents
* Get file metadata
* Follow symbolic links
* Calculate directory sizes

#### Writing

* Create files and directories
* Copy files (SFTP → SFTP, local → SFTP, SFTP → local)
* Move/rename files
* Delete files and directories
* Create symbolic links
* Create hard links (if supported by server)

#### Bulk Operations

* Copy multiple files
* Bulk rename
* Multi-select operations
* Progress tracking for large transfers

### Implementation

The SFTP provider is implemented in `yazi-vfs/src/provider/sftp/sftp.rs:78`:

```rust theme={null}
async fn copy<P>(&self, to: P, attrs: yazi_fs::provider::Attrs) -> io::Result<u64> {
    let to = to.as_path().as_unix()?;
    let attrs = super::Attrs(attrs).try_into().unwrap_or_default();

    let op = self.op().await?;
    let from = op.open(self.path, Flags::READ, &Attrs::default()).await?;
    let to = op.open(to, Flags::WRITE | Flags::CREATE | Flags::TRUNCATE, &attrs).await?;

    let mut reader = BufReader::with_capacity(524288, from);
    let mut writer = BufWriter::with_capacity(524288, to);
    let written = tokio::io::copy(&mut reader, &mut writer).await?;

    writer.flush().await?;
    if !attrs.is_empty() {
        writer.get_ref().fsetstat(&attrs).await.ok();
    }

    writer.shutdown().await.ok();
    Ok(written)
}
```

Note the 512KB buffers for optimal throughput.

### Progress Tracking

Large SFTP transfers show progress:

```rust theme={null}
fn copy_with_progress<P, A>(&self, to: P, attrs: A) 
    -> io::Result<Receiver<io::Result<u64>>> 
{
    let to = UrlBuf::Sftp {
        loc: LocBuf::saturated(to.as_path().to_unix_owned()?, SchemeKind::Sftp),
        domain: self.name.intern(),
    };
    let from = self.url.to_owned();

    Ok(crate::provider::copy_with_progress_impl(from, to, attrs.into()))
}
```

Progress updates stream via channel for real-time UI updates.

## Cross-Provider Operations

The VFS seamlessly handles operations across different providers:

### Local ↔ SFTP

```rust theme={null}
pub async fn copy<U, V>(from: U, to: V, attrs: Attrs) -> io::Result<u64> {
    let (from, to) = (from.as_url(), to.as_url());

    match (from.kind().is_local(), to.kind().is_local()) {
        (true, true) => Local::new(from).await?.copy(to.loc(), attrs).await,
        (false, false) if from.scheme().covariant(to.scheme()) => {
            Providers::new(from).await?.copy(to.loc(), attrs).await
        }
        (true, false) | (false, true) | (false, false) => 
            super::copy_impl(from, to, attrs).await,
    }
}
```

Yazi automatically:

* Routes to appropriate provider
* Handles different path formats
* Preserves attributes when possible
* Shows unified progress tracking

## Capabilities System

Providers declare their capabilities:

```rust theme={null}
pub struct Capabilities {
    pub symlink: bool,
}

fn capabilities(&self) -> Capabilities { 
    Capabilities { symlink: true } 
}
```

This enables:

* Feature detection
* Graceful degradation
* Provider-specific optimizations
* Error prevention

## Metadata Handling

The VFS normalizes metadata across providers:

```rust theme={null}
pub async fn metadata<U>(url: U) -> io::Result<Cha> {
    Providers::new(url.as_url()).await?.metadata().await
}
```

`Cha` (characteristics) includes:

* File type (regular, directory, symlink)
* Permissions
* Size
* Modified time
* Link target (for symlinks)

## Error Handling

VFS operations return standard I/O errors:

```rust theme={null}
pub enum ErrorKind {
    NotFound,
    PermissionDenied,
    ConnectionRefused,
    ConnectionReset,
    ConnectionAborted,
    NotConnected,
    AlreadyExists,
    Interrupted,
    InvalidInput,
    TimedOut,
    Unsupported,
    // ...
}
```

Errors are:

* **Consistent** - Same error types across providers
* **Actionable** - Clear error messages
* **Recoverable** - Retry logic for network issues

## Directory Reading

Directory listing works uniformly:

```rust theme={null}
pub async fn read_dir<U>(url: U) -> io::Result<ReadDir> {
    Providers::new(url.as_url()).await?.read_dir().await
}

// Usage
let mut it = read_dir(url).await?;
while let Some(entry) = it.next().await? {
    println!("{}", entry.name());
}
```

## Performance Optimizations

The VFS includes several performance optimizations:

### Connection Pooling

SFTP connections are pooled to avoid reconnection overhead.

### Buffered I/O

Large buffers (512KB) maximize throughput:

```rust theme={null}
let mut reader = BufReader::with_capacity(524288, from);
let mut writer = BufWriter::with_capacity(524288, to);
```

### Async Operations

All I/O is non-blocking and runs on Tokio runtime.

### Parallel Transfers

Multiple files transfer simultaneously when possible.

## Limitations

### Current Limitations

* **Trash not supported** - SFTP files are permanently deleted
* **No compression** - Files transfer uncompressed
* **SFTP only** - Other protocols (FTP, S3, etc.) not yet supported

### Future Plans

* Additional protocols (FTP, WebDAV, S3)
* Archive mounting (browse ZIP/TAR as directories)
* Custom search providers
* Cloud storage integration

## Advanced Usage

### Case-Insensitive Paths

The VFS handles case-insensitive filesystems:

```rust theme={null}
pub async fn casefold<U>(url: U) -> io::Result<UrlBuf> {
    Providers::new(url.as_url()).await?.casefold().await
}
```

This resolves ambiguous paths on case-insensitive systems.

### Absolute Path Resolution

```rust theme={null}
pub async fn absolute<'a, U>(url: &'a U) -> io::Result<UrlCow<'a>> {
    Providers::new(url.as_url()).await?.absolute().await
}
```

Converts relative paths to absolute.

### Identity Checking

```rust theme={null}
pub async fn identical<U, V>(a: U, b: V) -> io::Result<bool> {
    // Check if two URLs refer to the same file
}
```

Handles hard links and bind mounts correctly.

## See Also

* [Async Tasks](features/async-tasks) - Task system for VFS operations
* [DDS](features/dds) - Sync operations across instances
* [Configuration](configuration/yazi) - VFS configuration options
