Skip to content

File Operations

Read, write, sync, and manage files on remote hosts via SFTP.

Nefia provides file system subcommands and a directory sync command for working with files on remote hosts. All operations run over the encrypted VPN tunnel using SFTP.

Commands Overview

CommandDescription
nefia fs readRead a file from a remote host
nefia fs writeWrite a file to a remote host
nefia fs listList directory contents
nefia fs statShow file metadata
nefia syncSynchronise a local directory to remote hosts

The four fs subcommands require either --host (-H) or --session (-s) to specify the target. The --path flag is always required. The sync command uses --host or --target instead (see Directory Sync below).

Reading Files

Use nefia fs read to fetch the contents of a remote file and print them to stdout:

bash
nefia fs read --host my-server --path /etc/hostname
nefia fs read --host my-server --path /etc/hostname

my-server.prod.internal

Pipe the output to local tools for further processing:

bash
nefia fs read --host db-01 --path /etc/postgresql/16/main/postgresql.conf | grep max_connections

Base64 Output

Use --base64 to force base64-encoded output, useful for binary files:

bash
nefia fs read --host my-server --path /opt/app/icon.png --base64

Streaming Download with --out

Use --out to download a file directly to a local path. This streams the data from disk to disk without buffering in memory, supporting files up to 3 GB:

bash
nefia fs read --host my-server --path /var/backups/db-dump.sql.gz --out ./db-dump.sql.gz
nefia fs read --host web-01 --path /var/backups/db.sql.gz --out ./db.sql.gz

Downloading db.sql.gz... [===================> ] 48% 120.5 MB / 250.0 MB 15.2 MB/s ETA 9s

When the download completes, Nefia prints the total bytes transferred and the local destination path.

Writing Files

Use nefia fs write to upload content to a remote file. You must provide either --text or --in.

Text Content via --text

Pass text content directly with the --text flag:

bash
nefia fs write --host my-server --path /etc/app/config.txt --text "new-config-value"

Streaming Upload with --in

Use --in to upload a local file. This streams the data directly, supporting files up to 3 GB:

bash
nefia fs write --host my-server --path /opt/releases/app.tar.gz --in ./app.tar.gz
nefia fs write --host my-server --path /opt/releases/app.tar.gz --in ./app.tar.gz

Uploading app.tar.gz (1.2 GB)... [===================> ] 48% 576.0 MB / 1.2 GB 24.3 MB/s ETA 26s

Listing Directories

Use nefia fs list to view the contents of a remote directory:

bash
nefia fs list --host my-server --path /var/log/
nefia fs list --host my-server --path /var/log/

TYPE SIZE MTIME NAME dir 4096 2026-02-20T08:00:00Z nginx/ file 28672 2026-02-24T12:34:00Z syslog file 14336 2026-02-24T12:34:00Z auth.log file 8192 2026-02-23T00:00:00Z kern.log file 2048 2026-02-20T09:15:00Z dpkg.log

File Metadata

Use nefia fs stat to retrieve metadata for a single file or directory:

bash
nefia fs stat --host my-server --path /etc/nginx/nginx.conf
nefia fs stat --host my-server --path /etc/nginx/nginx.conf

Path: /etc/nginx/nginx.conf Type: file Size: 2847 bytes Permissions: -rw-r--r-- Modified: 2026-02-18 14:22:31

Transfer Progress

When downloading (--out) or uploading (--in), Nefia displays a progress bar showing transfer speed and estimated time remaining. The progress bar pre-fetches the remote file size (for downloads) or reads the local file size (for uploads) to show accurate percentages.

The progress bar adapts to the terminal:

  • TTY mode: The bar updates in place with real-time percentage, speed, and ETA.
  • Non-TTY mode: A summary line is printed at percentage milestones.

Use --quiet (-q) to suppress the progress bar entirely.

Transfer Resume

Interrupted file transfers can be resumed automatically. When a transfer fails mid-way, Nefia saves progress metadata in a .nefia.partial sidecar file. On retry, the transfer resumes from where it left off using single-pass SHA-256 verification.

This is particularly useful for large file transfers over unreliable connections — no need to re-transfer gigabytes of data after a brief network interruption.

JSON Output

All four subcommands support --output json (or -o json) for machine-readable output:

bash
nefia fs stat --host my-server --path /etc/hostname --output json
nefia fs list --host my-server --path /var/log/ --output json
nefia fs read --host my-server --path /etc/hostname --output json

Session-Based File Operations

Instead of specifying --host on every command, you can use a session. A session binds a host to a root directory, and all --path values are resolved relative to that root:

bash
# Open a session
nefia session open --host db-01 --root /etc/app
 
# File operations use relative paths within the session root
nefia fs read --session <id> --path config.yaml
nefia fs write --session <id> --path config.yaml --in ./new-config.yaml
nefia fs list --session <id> --path .
nefia fs stat --session <id> --path config.yaml
 
# Close the session
nefia session close <id>

The session acts as a sandbox: paths that attempt to escape the root directory (via ../) are rejected.

Timeouts

Individual SFTP operations are subject to a configurable timeout of 5 minutes by default. Adjust this with ssh.sftp_timeout_sec:

yaml
ssh:
  sftp_timeout_sec: 600  # 10 minutes

As a last resort, the transport layer applies a 30-minute hard safety timeout that activates only when no other deadline is set (e.g., when using SFTP via MCP without a request-level timeout). This prevents indefinite hangs on unresponsive peers. Streaming operations (fs read --out, fs write --in) are not subject to this safety timeout.

File Size Limits

By default, Nefia enforces a 10 MB maximum for inline file operations (fs read without --out, fs write --text). Streaming operations (fs read --out, fs write --in) support files up to 3 GB.

To change the maximum file size, update your nefia.yaml:

yaml
ssh:
  max_file_size_bytes: 3221225472  # 3 GB (default)

Directory Sync

Use nefia sync to synchronise an entire local directory to one or more remote hosts. Only changed files are transferred -- unchanged files are skipped automatically. This is the recommended way to deploy configuration directories, application bundles, or any tree of files that should match the local copy.

bash
nefia sync <local-dir> <remote-dir> --target <selector>

The command takes two positional arguments: the local directory to read from and the remote directory to write to. A target selector (--host or --target) is required.

Basic Usage

bash
# Sync a config directory to all hosts
nefia sync ./configs /etc/app/ --target all
 
# Sync to a single host
nefia sync ./deploy /opt/app/ --host my-pc
 
# Sync to a host group
nefia sync ./dist /var/www/html/ --target group:webservers

Change Detection

By default, Nefia compares files using size + modification time. If either differs, the file is re-transferred. For stricter comparison, use --checksum to compute a SHA256 hash of both the local and remote file:

bash
nefia sync ./configs /etc/app/ --target all --checksum

Dry Run

Use --dry-run to preview what would change without transferring any files:

bash
nefia sync ./configs /etc/app/ --target all --dry-run
nefia sync --dry-run

Syncing ./configs → /etc/app/ on 3 host(s) [DRY RUN] Local: 12 files, 48.2 KB

[web-01] transfer app.conf 2.1 KB (size changed) transfer routes.yaml 1.4 KB (new file) skip database.yaml Summary: 2 transfer, 10 skip (3.5 KB) [web-02] transfer app.conf 2.1 KB (size changed) transfer routes.yaml 1.4 KB (new file) skip database.yaml Summary: 2 transfer, 10 skip (3.5 KB) [web-03] skip app.conf transfer routes.yaml 1.4 KB (new file) skip database.yaml Summary: 1 transfer, 11 skip (1.4 KB)

The dry-run output lists each planned action (transfer, mkdir, delete, rmdir, skip) per host, along with file sizes and the reason for transfer.

Deleting Extra Remote Files

By default, files that exist on the remote host but not locally are left untouched. Use --delete to remove them:

bash
nefia sync ./configs /etc/app/ --target all --delete

When --delete is specified, Nefia prompts for confirmation before proceeding (unless --yes is passed). The prompt warns that remote-only files will be removed.

Excluding Files

Use --exclude to skip files matching glob patterns. The flag can be repeated:

bash
nefia sync ./project /opt/app/ --target all --exclude "*.log" --exclude ".git" --exclude "node_modules"

Excluded files are filtered from both the local scan and the remote comparison, so they are never transferred or deleted.

Concurrency

Sync runs against multiple hosts in parallel, controlled by the global --concurrency (-c) flag. Within each host, file transfers run with a per-host concurrency of 4 by default. Adjust this with --file-concurrency:

bash
nefia sync ./deploy /opt/app/ --target all --concurrency 10 --file-concurrency 8

Flags Reference

FlagTypeDefaultDescription
--checksumbooleanfalseUse SHA256 checksum for comparison instead of size+mtime
--deletebooleanfalseDelete remote files not present locally
--dry-runbooleanfalsePreview changes without transferring
--excludestring[]--Glob patterns to exclude (can be repeated)
--file-concurrencyint4Concurrent file transfers per host

Global flags --host (-H), --target (-t), --concurrency (-c), --yes (-y), and --output (-o) also apply.

JSON Output

Use --output json for machine-readable results. Each host entry includes transfer counts, byte totals, duration, and (in dry-run mode) the full action plan:

bash
nefia sync ./configs /etc/app/ --target all --output json
nefia sync ./configs /etc/app/ --target all --dry-run --output json

Error Handling

File operations return structured error codes for common failures:

CodeTitleDescription
E3001File not foundThe requested file does not exist on the remote host.
E3002Permission deniedThe SSH user lacks permission to access the file or directory.
E3003File too largeThe file exceeds the maximum allowed size for inline transfer. Use --out / --in for streaming.
E3004SFTP operation failedA general SFTP failure (e.g., subsystem not enabled, disk full).
E3005Path denied by policyThe path is outside allowed_roots or matches a deny_paths rule.

Use nefia explain <code> to see detailed resolution steps for any error code:

bash
nefia explain E3001

Nefia includes contextual information in error messages to help diagnose issues:

  • SFTP timeout errors include the operation name and a configuration hint. For example: sftp read timed out: the operation did not complete within the configured timeout (check defaults.timeout in config).
  • Streaming transfer errors include the number of bytes transferred before the failure, so you can tell how far the transfer progressed. For example: sftp stream read failed after 12345 bytes: connection reset.
  • Symlink rejections explain the security rationale: symlinks are rejected to prevent path traversal attacks; write to the resolved real path instead.

See the Error Codes reference for the full catalog of all error codes.

MCP Server Tools

The MCP server exposes 24 file operation tools for AI agents:

ToolDescription
nefia.fs.readRead file contents (text or base64 for binary).
nefia.fs.writeWrite or overwrite a file.
nefia.fs.patchApply a unified diff patch to a file.
nefia.fs.listList directory contents with metadata.
nefia.fs.statGet file metadata (size, permissions, timestamps).
nefia.fs.copyCopy a file on the remote host.
nefia.fs.moveMove or rename a file.
nefia.fs.removeDelete a file or directory.
nefia.fs.mkdirCreate a directory (with parents).
nefia.fs.chmodChange file permissions.
nefia.fs.chownChange file owner and group.
nefia.fs.findFind files matching name/size/time patterns.
nefia.fs.grepSearch file contents with regex.
nefia.fs.tailGet the last N lines of a file.
nefia.fs.duShow disk usage of a directory.
nefia.fs.diffShow unified diff between two files.
nefia.fs.symlinkCreate a symbolic link.
nefia.fs.readlinkRead the target of a symbolic link.
nefia.fs.archive.createCreate a tar.gz or zip archive.
nefia.fs.archive.extractExtract an archive to a directory.
nefia.fs.stream_readStream a large file download (up to 3 GB).
nefia.fs.stream_writeStream a large file upload (up to 3 GB).
nefia.fs.stream_read_resumableResumable streaming download with offset.
nefia.fs.stream_write_resumableResumable streaming upload with offset.
Remote Execution

Execute commands across multiple hosts with targeting and concurrency control.

Sessions

Manage scoped working contexts for file and exec operations.

CLI Reference

Complete reference for all file system commands and flags.