Skip to content

Sessions

Manage persistent SSH sessions on remote hosts.

Sessions provide a persistent context that binds a host, root directory, and working directory together. Instead of specifying the host and path for every file operation, you open a session once and then run commands within it — all confined to a sandboxed directory tree.

Why Sessions?

Without sessions, every nefia fs command requires --host and a full path. Sessions solve this by maintaining state across commands:

  • Context persistence — The host, root directory, and working directory carry over between commands.
  • Path sandboxing — All operations are confined to the root directory. SafeJoin prevents path traversal via ../, normalizes Windows backslashes and drive-letter roots, and rejects escapes such as UNC paths.
  • Automatic cleanup — Expired sessions are garbage-collected without manual intervention.

Opening a Session

Use nefia session open to create a new session bound to a host:

bash
nefia session open --host my-server --root /var/www/myapp
nefia session open

Session opened: a1b2c3d4 Host: my-server Root: /var/www/myapp Cwd: /var/www/myapp Shell: /bin/bash

The returned session ID is used for all subsequent operations within this session.

Flags

FlagDescription
--host(required) Host ID to open the session on
--rootRoot directory on the remote host (sandbox). Defaults to the host's configured root field, or the remote user's home directory
--cwdInitial working directory relative to root. Defaults to the root directory

Managing Sessions

List Active Sessions

bash
nefia session list
nefia session list

SESSION_ID HOST ROOT LAST_USED a1b2c3d4 my-server /var/www/myapp 2026-03-04T10:30:00Z f9e8d7c6 dev-box /home/deploy/app 2026-03-04T08:15:00Z

The list command performs a lazy garbage-collection pass, automatically removing any expired sessions before displaying results.

Close a Session

bash
nefia session close a1b2c3d4

You do not need to type the full session ID. Prefix matching works with a minimum of 8 characters.

Session ID Format

Session IDs are 64-character hex strings (32 bytes of cryptographic randomness). In display output, they are truncated to the first 8 characters for readability.

Prefix Matching

You only need to provide enough characters to uniquely identify a session. The minimum prefix length is 8 characters.

Use the --session (or -s) flag to target a session:

bash
nefia fs list --session a1b2c3d4 --path .
nefia fs read --session a1b2c3d4 --path config/app.yaml

Path Sandboxing

Every session is confined to its root directory. The SafeJoin function rejects any operation that would escape the sandbox:

bash
# This works — path is within the root
nefia fs read --session a1b2c3d4 --path config/app.yaml
 
# These are rejected on POSIX roots:
nefia fs read --session a1b2c3d4 --path ../../etc/passwd   # path traversal
nefia fs read --session a1b2c3d4 --path /etc/passwd         # absolute path

When the session root is a Windows path (for example C:\Users\app), backslashes are normalized to forward slashes and the result is kept inside that root (e.g. C:/Users/app/config.yaml). UNC paths and relative drive-letter escapes are rejected.

Path traversal rejected

Error: path denied: path escapes root: "../../etc/passwd"

Session TTL and Expiration

Sessions have a default time-to-live of 24 hours from the last use. After the TTL expires, the session can no longer be used — attempting to access it returns an error and automatically removes it from the store.

Configuring TTL

Set session_ttl_minutes in your nefia.yaml to override the default:

yaml
session_ttl_minutes: 480  # 8 hours instead of 24

A value of 0 uses the default 24-hour TTL.

LastUsedAt Tracking

Each time a session is accessed, its LastUsedAt timestamp is updated. To reduce disk I/O, updates are throttled to at most once per minute — rapid successive accesses within the same minute do not trigger additional disk writes.

Per-Client Session Limit

Each MCP client is limited to 50 concurrent sessions. Attempting to open a 51st session returns an error. Close unused sessions with nefia session close or nefia.session.close to free up capacity.

Session Ownership

Sessions are bound to the MCP client that created them. One client cannot list or close sessions created by another client. This isolation ensures that concurrent AI agents operating on the same Nefia instance do not interfere with each other's session state.

Garbage Collection

Nefia automatically cleans up expired sessions in the background. The garbage collector runs every 5 minutes by default and removes sessions that have exceeded their TTL.

Configuring GC Interval

Set session_gc_interval_minutes in your nefia.yaml:

yaml
session_gc_interval_minutes: 10  # run GC every 10 minutes

Storage Location

Sessions are persisted to a JSON file at:

  • macOS: ~/Library/Application Support/nefia/state/sessions.json
  • Linux: ~/.config/nefia/state/sessions.json
  • Windows: %AppData%\nefia\state\sessions.json

The file is written atomically (temp file, fsync, chmod 0600, rename) and protected by a cross-process file lock.

MCP Tool Integration

When using Nefia as an MCP server, sessions are managed through dedicated tools:

MCP ToolDescription
nefia.session.openOpen a new session (returns session_id)
nefia.session.closeClose a session by ID

Once a session is open, pass session_id to any file system tool instead of host_id:

plaintext
nefia.fs.read   { "session_id": "a1b2c3d4...", "path": "config/app.yaml" }
nefia.fs.write  { "session_id": "a1b2c3d4...", "path": "config/app.yaml", "content": "..." }
nefia.fs.list   { "session_id": "a1b2c3d4...", "path": "." }
nefia.fs.patch  { "session_id": "a1b2c3d4...", "path": "config/app.yaml", "patch": "..." }
nefia.exec      { "session_id": "a1b2c3d4...", "command": "ls -la" }

When using session_id, paths are resolved relative to the session's root directory and sandboxed by SafeJoin.

Working with File Operations

Sessions integrate directly with all nefia fs subcommands. Pass the --session flag to operate within a session context:

bash
# List files in the session's working directory
nefia fs list --session a1b2c3d4 --path .
 
# Read a file relative to the root directory
nefia fs read --session a1b2c3d4 --path config/database.yaml
 
# Write a file from local disk
nefia fs write --session a1b2c3d4 --path config/database.yaml --in ./local-database.yaml

Practical Workflow

Here is a typical session-based workflow for deploying a configuration update:

1

Open a session on the target host:

bash
nefia session open --host prod-web-1 --root /etc/nginx
2

Review the current configuration:

bash
nefia fs read --session a1b2c3d4 --path nginx.conf
nefia fs list --session a1b2c3d4 --path conf.d/
3

Upload the updated configuration:

bash
nefia fs write --session a1b2c3d4 --path conf.d/app.conf --in ./new-app.conf
4

Validate and reload Nginx:

bash
nefia exec --host prod-web-1 -- nginx -t && systemctl reload nginx
5

Close the session:

bash
nefia session close a1b2c3d4
CLI Reference

Full reference for all Nefia CLI commands including fs subcommands.

Host Management

Organize target PCs with hosts, groups, and tag-based targeting.