CLI Commands
Complete reference for all Nefia CLI commands and flags.
This page provides a complete reference for the nefia CLI. Commands are organized by function.
When invoked with no arguments in a terminal, nefia launches the interactive TUI dashboard.
Global Flags
These persistent flags are available on all commands:
| Flag | Type | Default | Description |
|---|---|---|---|
--config | string | auto | Path to nefia.yaml configuration file |
-o, --output | string | config default (human) | Output format: human, table, json, jsonl, yaml, or compact |
--json | boolean | false | Shorthand for --output json |
--jq | string | — | jq expression to filter JSON output. Implies --json |
--no-color | boolean | false | Disable color output |
-q, --quiet | boolean | false | Suppress non-essential output |
-v, --verbose | boolean | false | Enable verbose output |
--debug | boolean | false | Enable debug output |
-T, --timeout | duration | config default (30m) | Execution timeout (e.g. 60s, 5m, 1h30m) |
-c, --concurrency | int | 0 | Maximum number of concurrent hosts (0 = use config default) |
-t, --target | string | — | Target selector expression: host:<id>, group:<name>, tag:<key>=<value>, all, regex ~..., file @path, stdin -, plus ,, !, and & operators |
-H, --host | string | — | Single host ID (shorthand for --target host:<id>) |
-s, --session | string | — | Session ID (prefix match, min 8 chars) |
-y, --yes | boolean | false | Skip standard interactive confirmations (named risk prompts still require --accept-risk) |
--fail-fast | boolean | false | Stop on first failure |
--min-success-rate | float | 0.0 | Minimum required success rate (0.0-1.0); aborts early if mathematically impossible |
--notify | boolean | false | Send a desktop notification when the operation completes |
--team | string | — | Team slug to use for this command (overrides NEFIA_TEAM env var and config) |
--profile | string | — | Load an alternate config profile from ~/.config/nefia/profiles/ |
--retry-timeout | duration | config default (30s) | Max wait time for automatic VPN recovery retry |
--wait-for-vpn | boolean | false | Wait for the VPN tunnel to become healthy before executing |
--insecure-skip-hostkey-check | boolean | false | Skip SSH host key verification (INSECURE) |
--allow-absolute-root | boolean | false | Allow absolute paths as root directories |
--accept-risk | string | — | Accept named risk prompts for destructive/security-sensitive operations (for example disconnect-peers,rotate-key,revoke-all) |
Setup Commands
setup
Guided first-time onboarding that creates config, generates VPN keys, and can invite a host.
nefia setup [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--non-interactive | boolean | false | Skip the interactive setup wizard |
--host-name | string | — | Host name to invite in non-interactive mode |
--host-os | string | — | Host OS for non-interactive mode (macos, linux, windows) |
--skip-host | boolean | false | Create config and keys without generating an invite token |
setup is the canonical command. nefia init remains available as an alias for backward compatibility.
The setup flow is idempotent and runs four phases:
- Check or create
nefia.yaml - Check or generate the operator WireGuard keypair
- Optionally collect the first host's details
- Generate an invite token for that host
In interactive mode, Nefia can open the browser automatically if login is required before generating the invite. In non-interactive mode, pass --host-name and --host-os to generate an invite token, or --skip-host to stop after config and key setup.
# Initialize config and keys only
nefia setup --skip-host
# Full unattended bootstrap
nefia setup --non-interactive --host-name my-server --host-os linuxlogin
Authenticate with your Nefia account.
nefia loginUses challenge-response authentication: the CLI generates a verifier and challenge, opens the browser for approval, then polls until the approval completes. No local HTTP server is required. On success, stores a refresh token in your OS keyring (macOS Keychain, Linux Secret Service, Windows Credential Manager). See Authentication for details.
logout
Remove stored authentication tokens.
nefia logoutCore Commands
exec
Execute a command on one or more remote hosts.
nefia exec [flags] -- <command>The -- separator is required to distinguish nefia flags from the remote command. Everything after -- is concatenated and executed as a single shell command on the remote host(s).
| Flag | Type | Default | Description |
|---|---|---|---|
-n, --dry-run | boolean | false | Preview what would be executed without running |
--rerun | string | — | Rerun against hosts from the last multi-host execution (failure or success) |
--when-online | boolean | false | Queue the command for offline hosts and execute it when they come online |
--queue-ttl | duration | 24h | TTL for queued commands created by --when-online |
--stream | boolean | false | Stream per-host output in real time with host prefixes |
--log-dir | string | — | Write per-host output to separate files in this directory |
--out-file | string | — | Also write aggregate output to a single file |
--batch-size | int | 0 | Execute on N hosts at a time (0 = all at once) |
--batch-percent | int | 0 | Execute on P% of hosts per batch (1-100, mutually exclusive with --batch-size) |
--batch-wait | duration | — | Wait between execution batches |
--subset | int | 0 | Execute on a random subset of N hosts |
Examples:
# Run on a single host
nefia exec --host my-server -- uname -a
# Run on all hosts in a group
nefia exec --target group:webservers -- systemctl status nginx
# Run on all hosts with fail-fast
nefia exec --target all --fail-fast -- apt update
# Run within a session context
nefia exec --session <id> -- ls -la /tmp
# Queue for offline hosts
nefia exec --target group:laptops --when-online --queue-ttl 48h -- softwareupdate --install --allMCP-Only Parameters:
When using nefia.exec via MCP, these additional parameters are available:
| Parameter | Type | Description |
|---|---|---|
stdin | string | Input data to pipe to the command's stdin. |
working_directory | string | Override the working directory for command execution. |
uid | string | Run as this user/uid on the target host. |
ssh
Open an interactive SSH session to a remote host via VPN tunnel.
nefia ssh <host-id> [-- <command>]Opens a fully interactive SSH terminal session to the specified host. If a command is provided after --, it runs non-interactively and returns the output.
Arguments:
| Argument | Description |
|---|---|
host-id | The target host identifier. |
command | Optional command to run non-interactively. |
Examples:
# Interactive SSH session
nefia ssh my-pc
# Run a single command
nefia ssh my-pc -- whoami
# Run a command with arguments
nefia ssh my-pc -- ls -la /var/logAll traffic flows through the WireGuard VPN tunnel. The host must have an active VPN configuration.
fs
Remote file system operations.
fs read -- Read a file
nefia fs read --host <id> --path <remote-path> [--base64] [--out <local-path>]| Flag | Type | Default | Description |
|---|---|---|---|
--path | string | required | Remote file path |
--base64 | boolean | false | Force base64-encoded output |
--out | string | — | Download to local file (streaming, supports large files up to 3 GB) |
Reads a file from the remote host and prints its contents to stdout. When --out is provided, the file is streamed directly to a local path without buffering in memory.
# Read and display
nefia fs read --host web-1 --path /etc/hostname
# Download a large log file
nefia fs read --host web-01 --path /var/log/app/access.log --out ./access.logfs write -- Write a file
nefia fs write --host <id> --path <remote-path> [--text <content>] [--in <local-path>]| Flag | Type | Default | Description |
|---|---|---|---|
--path | string | required | Remote file path |
--text | string | — | Inline text content to write |
--in | string | — | Upload a local file (streaming, supports large files up to 3 GB) |
Writes content to a file on the remote host. One of --text or --in is required. When --in is provided, the local file is streamed directly without buffering in memory.
# Write inline text
nefia fs write --host web-1 --path /tmp/hello.txt --text "Hello"
# Upload a local file
nefia fs write --host db-01 --path /tmp/backup.sql.gz --in ./backup.sql.gzfs list -- List directory contents
nefia fs list --host <id> --path <remote-path>Lists files and directories at the specified remote path. Displays type, size, modification time, and name.
fs stat -- Show file metadata
nefia fs stat --host <id> --path <remote-path>Displays file metadata including path, type, size, permissions, and modification time. Use --output json for structured output.
push
Push a local file to multiple remote hosts in parallel.
nefia push <local-file> <remote-path>The remote path must be the full destination file path (not a directory). The local file is read into memory only after target resolution and policy checks succeed, saving memory when validation fails.
| Flag | Type | Default | Description |
|---|---|---|---|
-n, --dry-run | boolean | false | Preview what would be pushed without transferring |
--batch-size | int | 0 | Push to N hosts at a time (0 = all at once) |
--batch-percent | int | 0 | Push to P% of hosts per batch (1-100, mutually exclusive with --batch-size) |
--batch-wait | duration | — | Wait between batches |
--subset | int | 0 | Push to a random subset of N hosts |
# Deploy a config file to all web servers
nefia push --target group:webservers ./nginx.conf /etc/nginx/nginx.conf
# Push to a single host
nefia push --host my-pc ./script.sh /tmp/script.shsync
Synchronize a local directory to remote hosts via SFTP.
nefia sync <local-dir> <remote-dir>Only changed files are transferred (based on size and modification time by default). Use --checksum for SHA256-based comparison.
| Flag | Type | Default | Description |
|---|---|---|---|
--checksum | boolean | false | Use SHA256 checksum for comparison instead of size+mtime |
--delete | boolean | false | Delete remote files not present locally |
-n, --dry-run | boolean | false | Preview changes without transferring |
--exclude | string[] | — | Glob patterns to exclude (can be repeated) |
--file-concurrency | int | 4 | Concurrent file transfers per host |
--batch-size | int | 0 | Sync to N hosts at a time (0 = all at once) |
--batch-percent | int | 0 | Sync to P% of hosts per batch (1-100, mutually exclusive with --batch-size) |
--batch-wait | duration | — | Wait between batches |
--subset | int | 0 | Sync to a random subset of N hosts |
# Sync app directory with preview
nefia sync --target group:webservers --dry-run ./dist /opt/app/dist
# Sync with cleanup of removed files
nefia sync --target all --delete --exclude "*.log" ./config /etc/myappplan exec
Create an execution plan for review before applying.
nefia plan exec [flags] -- <command>| Flag | Type | Default | Description |
|---|---|---|---|
--out | string | plan.json | Output plan file path |
Generates a JSON execution plan that captures the target hosts, command, and policy evaluation so you can review what will happen before executing.
# Generate plan
nefia plan exec --target all -- systemctl restart nginx --out plan.json
# Review the plan
cat plan.json
# Apply the plan
nefia apply plan.jsonapply
Execute a saved execution plan.
nefia apply <plan-file>Runs a JSON execution plan generated by nefia plan exec. Shows a summary and prompts for confirmation before executing.
Session Commands
Session commands and their subcommands do not require authentication. They work without nefia login.
session open
Create a persistent session bound to a host and root directory.
nefia session open --host <id> [--root <dir>] [--cwd <dir>]| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | host configured root (or remote home) | Root directory on the remote host (sandbox: paths cannot escape it) |
--cwd | string | root | Initial working directory relative to root |
Returns a session ID for subsequent file and exec operations.
session close
Close an active session.
nefia session close <session-id> [--summary]| Flag | Type | Default | Description |
|---|---|---|---|
--summary | boolean | false | Generate and display a session summary after closing |
When --summary is provided, a structured summary of session activity is generated and printed before the session is closed.
session list
List all active sessions.
nefia session listsession recordings -- List saved terminal recordings
nefia session recordings [--limit N]| Flag | Type | Default | Description |
|---|---|---|---|
--limit | int | 0 | Limit the number of recordings shown (0 = all) |
Lists saved session recordings with session ID, size, and creation time.
session replay -- Replay a recording locally
nefia session replay <session-id> [--speed <factor>]| Flag | Type | Default | Description |
|---|---|---|---|
--speed | float | 1 | Playback speed (0 = instant, 1 = real-time, 5 = 5x) |
Replays a stored session recording to the terminal. Press Ctrl+C to stop replay cleanly.
session export -- Export a recording as .cast
nefia session export <session-id> [--out <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--out | string | <session-id>.cast | Output file path |
Exports a saved recording as an asciinema-compatible .cast file.
session summary
Generate an AI-consumable summary of a session.
nefia session summary <session-id>Generates a structured summary of session activity from audit records. The summary includes commands executed, files read/written, error count, duration, and a markdown narrative. It is persisted to disk and can be retrieved later.
nefia session summary <session-id>
nefia session summary <session-id> --output jsonping
Test point-to-point VPN latency to a specific host.
nefia ping <host-id> [flags]| Flag | Type | Default | Description |
|---|---|---|---|
-n, --count | int | 5 | Number of probes to send (0 = until interrupted) |
--interval | duration | 1s | Interval between probes |
--timeout | duration | 5s | Per-probe timeout |
--ssh | boolean | false | Also verify that the remote SSH daemon responds |
Creates a temporary tunnel, probes the target VPN address, and prints aggregate loss and latency statistics.
VPN Commands
vpn keygen -- Generate WireGuard keypair
nefia vpn keygen [--force]| Flag | Type | Default | Description |
|---|---|---|---|
--force | boolean | false | Overwrite existing keypair without confirmation |
Generates a new WireGuard keypair and saves it to your configuration. The private key is stored in the OS keyring when possible, falling back to plaintext in the config file. Usually done automatically by nefia setup.
vpn show-config -- Display VPN configuration
nefia vpn show-configDisplays the current VPN configuration including public key, listen port (port 0 is resolved to the default 51820), address, and all configured peers.
vpn invite -- Generate enrollment token
nefia vpn invite --name <hostname> --os <macos|linux|windows> [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | required | Hostname for the target. Must match ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,62}$. |
--os | string | required | Target OS: macos, linux, or windows |
--endpoint | string | — | Operator's public endpoint (ip:port) for direct connection |
--stun | boolean | false | Use STUN to discover public endpoint |
--ttl | duration | 24h | Token validity duration |
--enroll-port | int | 19820 | Enrollment listener port |
--listen | boolean | true | Start enrollment listener after generating invite |
--listen-timeout | duration | 60m | Enrollment listener timeout |
--token-out | string | — | Write the raw token to a file (permissions: 0600) instead of printing to stdout |
--copy | boolean | false | Copy the invite token to the system clipboard |
--fleet | boolean | false | Create a fleet token for multi-agent self-registration |
--count | int | 0 | Max uses for fleet token (0 = unlimited, only with --fleet) |
--approval-mode | string | auto-approve | Approval mode for fleet enrollment: auto-approve or require-approval |
--no-print-token | boolean | false | Suppress human-readable token output (useful for TUI and internal automation) |
Creates a single-use, HMAC-SHA256 signed enrollment token for a new target PC. When --fleet is used, creates a multi-use fleet token that allows multiple agents to enroll without individual invitations. If the operator is logged in, a cloud relay session is also created so agents behind NAT can enroll without a direct connection.
If neither a direct endpoint nor cloud relay is available, the command returns an error instead of creating an unusable invite.
After generating the token, vpn invite prints platform-specific installation instructions including a one-liner command to run on the target PC.
vpn reinvite -- Regenerate enrollment token
nefia vpn reinvite --name <hostname> [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | required | Host ID to reinvite |
--os | string | existing | Override target OS: macos, linux, or windows |
--endpoint | string | — | Operator's public endpoint (ip:port) |
--stun | boolean | false | Use STUN to discover endpoint |
--ttl | duration | 24h | Token validity duration |
--enroll-port | int | 19820 | Enrollment listener port |
--listen | boolean | true | Start enrollment listener after generating invite |
--listen-timeout | duration | 60m | Enrollment listener timeout |
--token-out | string | — | Write the raw token to a file (permissions: 0600) |
--copy | boolean | false | Copy the invite token to the system clipboard |
--no-print-token | boolean | false | Suppress human-readable token output (useful for TUI and internal automation) |
Regenerates an invite token for an existing host. The host is reset to pending status while preserving its VPN address. Use this when a previous invite has expired or when re-enrolling an active host.
# Regenerate expired invite
nefia vpn reinvite --name my-server --stun
# Change OS and regenerate
nefia vpn reinvite --name my-server --os linux --endpoint 203.0.113.10:51820vpn listen -- Start enrollment listener
nefia vpn listen [--timeout <duration>] [--count <n>]| Flag | Type | Default | Description |
|---|---|---|---|
--timeout | duration | 60m | Max time to wait per enrollment |
--count | int | 0 | Number of enrollments to accept. 0 enrolls all pending hosts, automatically stopping when none remain. |
Listens for incoming enrollment requests from target PCs. When --count is set, the listener stops automatically after the specified number of successful enrollments.
The listener prints a heartbeat progress message every 30 seconds while waiting for enrollments.
# Enroll all pending hosts
nefia vpn listen --count 0
# Enroll exactly 3 hosts with a longer timeout
nefia vpn listen --count 3 --timeout 2hvpn enroll-status -- Check enrollment status
nefia vpn enroll-status --name <name>Checks the enrollment status of a specific host. Displays host ID, status, VPN address, public key, and expiration. Warns when an invite has expired.
vpn status -- Show connection status
nefia vpn status [--live] [--ping]| Flag | Type | Default | Description |
|---|---|---|---|
--live | boolean | false | Start tunnel and show real-time peer stats |
--ping | boolean | false | Test TCP connectivity to each active peer (3s timeout) |
Without --live, displays VPN configuration status and peer list. With --live, starts the tunnel and shows real-time peer statistics including endpoint, handshake timestamps, transfer counters, and MagicDNS records. Peers with no recent handshake are marked STALE.
The --ping flag tests TCP connectivity to each active peer using the SSH port from host configuration, falling back to port 22.
vpn diagnose -- Run VPN diagnostics
nefia vpn diagnose [--host <id>]| Flag | Type | Default | Description |
|---|---|---|---|
--host | string | — | Diagnose a specific host only |
Runs comprehensive diagnostic checks on VPN configuration, peer validation, and connectivity. Reports results as [PASS], [WARN], or [FAIL].
Diagnostic checks include:
- Latency measurement: Each active peer is probed with a TCP dial. Results are classified as
[FAST](< 500ms),[OK](< 2s), or[SLOW](> 2s). - Route conflict detection: Checks for overlapping routes between the VPN subnet and existing network interfaces. Detects subnet conflicts that can cause routing failures.
vpn rotate-key -- Rotate WireGuard key
nefia vpn rotate-key [--grace-period <duration>]| Flag | Type | Default | Description |
|---|---|---|---|
--grace-period | duration | 72h | Grace period for old key retention |
Generates a new WireGuard keypair and stores it. After rotation, run nefia vpn push-key to distribute the new public key to all active hosts. The result includes a Warning field when there are conditions that require attention (e.g. hosts that could not be reached during rotation).
vpn push-key -- Distribute public key
nefia vpn push-key [--host <id>]| Flag | Type | Default | Description |
|---|---|---|---|
--host | string | — | Push key to a specific host only |
Pushes the current operator public key to all active VPN peers. If a key rotation is in progress, the command temporarily uses the previous key to reach hosts that have not yet received the new key.
vpn token-info -- Inspect an invite token
nefia vpn token-info --token <token>| Flag | Type | Default | Description |
|---|---|---|---|
--token | string | required | The invite token string to inspect |
Display the contents of an invite token without verifying the signature. Useful for inspecting token payloads, checking expiry, and debugging enrollment issues.
Host ID: mac-dev VPN Address: 10.99.0.2 Operator PK: xYz1...aBcD= Endpoint: 203.0.113.10:19820 Nonce: a1b2c3... Expires At: 2026-03-02T12:00:00Z (expires in 23h45m)
If the token has expired, the output shows an [EXPIRED] label:
Host ID: mac-dev ... Expires At: 2026-02-28T12:00:00Z [EXPIRED] 2d5h ago
vpn approve -- Approve pending host(s) for VPN access
nefia vpn approve --name <hostname>
nefia vpn approve --all --accept-risk=approve-all| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | — | Pending host ID to approve |
--all | boolean | false | Approve all pending-approval hosts |
--timeout | duration | 60m | Max time to wait for the approved host to enroll |
--accept-risk | string | — | Required risk acknowledgment when using --all (must be approve-all) |
Approve a specific pending host or all pending-approval hosts.
For hosts enrolled via single-use tokens (status: pending), opens a targeted enrollment listener and waits for the agent to connect. For hosts enrolled via fleet tokens (status: pending-approval), immediately transitions the host to active status.
The --name and --all flags are mutually exclusive. When using --all, you must pass --accept-risk=approve-all to explicitly acknowledge the bulk operation. The --yes flag does not bypass this requirement.
# Approve and wait for a pending host
nefia vpn approve --name my-pc
# Approve a fleet-enrolled host immediately
nefia vpn approve --name fleet-host-1
# Approve all pending-approval hosts at once
nefia vpn approve --all --accept-risk=approve-allvpn fleet list -- List active fleet tokens
nefia vpn fleet listLists all active fleet tokens. Each entry shows the token nonce, usage count (used/max or used/inf for unlimited), approval mode, expiry status, and creation time.
Create a fleet token with nefia vpn invite --fleet.
vpn fleet revoke -- Revoke a fleet token
nefia vpn fleet revoke <nonce>Revokes the fleet token identified by the given nonce. Once revoked, no new agents can enroll using that token. Hosts that have already enrolled are not affected.
Team Management Commands
team list
List all teams you belong to.
nefia team listDisplays a table of teams with slug, name, plan, your role, member count, and host count. The currently active team is marked with *.
team current
Show the currently active team.
nefia team currentDisplays the active team's slug, name, ID, plan, your role, member count, and host count. If no team is selected, shows "personal" (your default workspace).
Running nefia team with no subcommand also shows the current team.
team use
Switch the active team.
nefia team use <slug>Sets the active team for subsequent commands. The choice is persisted to the config file. Use personal to switch back to your personal workspace.
It can also be overridden per-command with --team or the NEFIA_TEAM environment variable.
team create
Create a new shared team.
nefia team create --name <name>| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | required | Display name for the team |
Creates a new team and sets you as the owner. A URL-safe slug is generated from the name.
team invite
Generate an invitation code for the active team.
nefia team invite [--role MEMBER|ADMIN] [--max-uses N] [--expires H]| Flag | Type | Default | Description |
|---|---|---|---|
--role | string | MEMBER | Role to assign to invitees: MEMBER or ADMIN |
--max-uses | int | 1 | Maximum number of times the code can be used (1-100) |
--expires | int | 48 | Expiration in hours (max: 168) |
Generates a single-use or multi-use invitation code. Requires ADMIN or OWNER role.
team join
Join a team via invitation code.
nefia team join <code>Joins the team associated with the invitation code. The code must be valid, unexpired, and not fully used.
team members
List members of the active team.
nefia team membersDisplays a table of team members with email, name, role, and join date.
team role
Change a member's role in the active team.
nefia team role <email> --role <ADMIN|MEMBER>| Flag | Type | Default | Description |
|---|---|---|---|
--role | string | required | New role for the member (ADMIN or MEMBER) |
Requires OWNER role. Cannot demote the last owner of a team.
team leave
Leave the active team.
nefia team leaveRemoves you from the active team and switches to your personal workspace. You cannot leave your personal team. Team owners must transfer ownership first.
Configuration Commands
config show
Show the resolved configuration with source annotations.
nefia config show [--reveal] [--filter <substring>]| Flag | Type | Default | Description |
|---|---|---|---|
--reveal | boolean | false | Show sensitive values such as keys, tokens, and passwords |
--filter | string | — | Filter displayed keys by substring |
By default, sensitive fields are masked. Sources are annotated as config file, environment override, or default.
config ssh-config
Generate OpenSSH config entries for Nefia-managed hosts.
nefia config ssh-config [--write] [--identity-file <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--write | boolean | false | Write directly to ~/.ssh/config.d/nefia instead of stdout |
--identity-file | string | auto-detect | SSH private key path to include in generated host blocks |
Hosts with active VPN addresses use the VPN IP as HostName. Pending hosts are skipped.
Profile Commands
profile list
List available config profiles.
nefia profile listProfiles live under ~/.config/nefia/profiles/. The active profile is marked with * when --profile or NEFIA_PROFILE is set.
profile show
Show the raw contents of a profile file.
nefia profile show <name>Displays the profile path and YAML content.
profile create
Create a new profile from the built-in template.
nefia profile create <name>Writes a starter profile file and prints example activation commands.
Host Management Commands
hosts list
List all configured hosts.
nefia hosts listDisplays a table of all hosts with ID, address, OS, user, VPN status, and tags.
hosts show
Display detailed host information.
nefia hosts show <host-id>hosts remove
Remove a host from configuration.
nefia hosts remove <host-id>hosts import -- Import hosts from external sources
nefia hosts import --from <source> [--file <path>] [--dry-run]| Flag | Type | Default | Description |
|---|---|---|---|
--from | string | — | Source type: ssh-config, ansible-inventory, known-hosts, csv (required) |
--file | string | auto | Source file path (optional for ssh-config and known-hosts, required for ansible-inventory and csv) |
--dry-run | boolean | false | Show what would be imported without making changes |
Parses hosts from external sources and adds new hosts to your configuration. Existing hosts are skipped. Imported hosts receive address, user, and port settings but no VPN configuration.
CSV files require a header row with at least one of: id, hostname, host, address, or ip. Optional columns: user, os, port, tags.
# Import from default SSH config
nefia hosts import --from ssh-config
# Import from Ansible inventory
nefia hosts import --from ansible-inventory --file inventory.yml
# Preview what would be imported
nefia hosts import --from known-hosts --dry-run
# Import from CSV without prompting
nefia hosts import --from csv --file hosts.csv --yeshosts refresh -- Refresh host metadata via SSH
nefia hosts refresh [--target <selector>] [--categories <list>]| Flag | Type | Default | Description |
|---|---|---|---|
--target | string | all | Host selector (host ID, group name, or tag selector) |
--categories | string | all | Fact categories to collect (comma-separated: os, disk, memory, cpu, uptime, network) |
Connects to hosts via SSH and collects system metadata (OS, CPU, memory, network). Only hosts with active VPN connections are probed. Collected metadata is stored in the host's meta field in nefia.yaml.
# Refresh all active hosts
nefia hosts refresh
# Refresh a specific host
nefia hosts refresh --target host-1
# Collect only specific categories
nefia hosts refresh --categories os,cpurevoke
Emergency revoke of a host's VPN access.
nefia revoke <host>
nefia revoke --all --accept-risk=revoke-allrevoke clears the stored peer configuration and removes the host from inventory so future reconnection attempts fail immediately.
groups list
List all configured host groups.
nefia groups listShows groups with their tag filter criteria.
power wake
Wake an offline host with Wake-on-LAN.
nefia power wake <host> [--proxy <online-host>] [--wait] [--timeout <duration>]| Flag | Type | Default | Description |
|---|---|---|---|
--proxy | string | auto | Online proxy host that sends the WoL magic packet |
--wait | boolean | false | Poll until the target host comes back online |
--timeout | duration | 60s | Timeout used with --wait |
Nefia resolves the target MAC from host.mac first, then from collected host metadata. If you omit --proxy, it tries to find an active agent on the same /24 subnet automatically.
recording
Manage session recordings (asciinema v2 .cast.gz files). Recording commands and their subcommands do not require authentication and work without nefia login.
recording list -- List session recordings
nefia recording list [--limit <N>]| Flag | Type | Default | Description |
|---|---|---|---|
--limit | int | 0 | Limit number of recordings shown (0 = all) |
Lists session recordings with session ID, host, user, date, duration, and file size.
recording replay -- Replay a recording in the terminal
nefia recording replay <session-id> [--speed <factor>]| Flag | Type | Default | Description |
|---|---|---|---|
--speed | float | 1 | Playback speed (0 = instant, 1 = real-time, 5 = 5x) |
Replays a stored session recording to the terminal. Press Ctrl+C to stop replay cleanly.
recording export -- Export a recording as .cast
nefia recording export <session-id> [--out <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--out | string | <session-id>.cast | Output file path |
Exports a saved recording as an asciinema-compatible .cast file.
recording delete -- Delete a recording
nefia recording delete <session-id>Deletes a recording file. Prompts for confirmation before deleting. Use --yes to skip.
Playbook Commands
playbook run
Execute a playbook against target hosts.
nefia playbook run <name-or-path> [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--var | string[] | — | Template variable override (key=value, can be repeated) |
--dry-run | boolean | false | Preview execution plan without running |
--step-timeout | duration | — | Default step timeout (e.g. 60s, 5m) |
Playbooks are discovered from search paths (in priority order):
- Direct file path (if path separator or
.yaml/.ymlextension present) ./playbooks/<name>.yaml- User config directory (e.g.
~/.config/nefia/playbooks/<name>.yaml)
nefia playbook run setup-monitoring --target group:webservers
nefia playbook run ./playbooks/deploy.yaml --target all --dry-run
nefia playbook run security-baseline --host pc-office --var port=9100playbook validate
Validate playbook YAML syntax.
nefia playbook validate <path>playbook list
List available playbooks from the search paths.
nefia playbook listplaybook show
Display playbook details including name, description, variables, and all steps.
nefia playbook show <name-or-path>Schedule Commands
schedule create -- Create a schedule
nefia schedule create --name <name> --cron <expr> --playbook <file> --target <selector> [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | required | Schedule name |
--cron | string | required | Cron expression (e.g. "0 2 * * *") |
--playbook | string | required | Playbook name or path |
--target | string | required | Target selector (all, host:<id>, group:<name>) |
--var | string[] | — | Template variable override (key=value) |
--timezone | string | local | IANA timezone (e.g. Asia/Tokyo) |
--overlap-policy | string | — | Overlap policy: skip, cancel_running, allow |
--missed-run-policy | string | — | Missed run policy: skip, run_once |
--description | string | — | Optional description |
Creates a cron-based schedule for recurring playbook execution. After creation, shows the next 3 upcoming runs.
nefia schedule create --name daily-backup --cron "0 2 * * *" --playbook backup --target all
nefia schedule create --name hourly-check --cron "0 * * * *" --playbook health --target group:web --timezone Asia/Tokyoschedule list -- List all schedules
nefia schedule listShows all schedules with their name, cron expression, playbook, target, status (enabled/disabled), and last run time. Also displays whether the daemon is running.
schedule show -- Show schedule details
nefia schedule show <id-or-name>Displays full schedule details including cron description, variables, overlap/missed-run policies, last run status, and the next 5 upcoming runs.
schedule update -- Modify a schedule
nefia schedule update <id-or-name> [flags]| Flag | Type | Description |
|---|---|---|
--cron | string | New cron expression |
--playbook | string | New playbook name or path |
--timezone | string | New IANA timezone |
--overlap-policy | string | Overlap policy |
--missed-run-policy | string | Missed run policy |
--description | string | New description |
--enabled | string | Enable/disable (true or false) |
schedule delete -- Remove a schedule
nefia schedule delete <id-or-name>Prompts for confirmation before deleting. Use --yes to skip.
schedule enable / disable -- Toggle a schedule
nefia schedule enable <id-or-name>
nefia schedule disable <id-or-name>schedule history -- Show execution history
nefia schedule history [id-or-name] [--limit N]| Flag | Type | Default | Description |
|---|---|---|---|
--limit | int | 20 | Maximum number of records to show |
Shows execution history with start time, schedule name, trigger type, status, duration, and host success counts. When called without an argument, shows history for all schedules.
schedule trigger -- Manually trigger a schedule
nefia schedule trigger <id-or-name>Runs the schedule's playbook immediately, bypassing the cron expression. The schedule does not need to be enabled. This command executes the playbook directly and does not require the daemon to be running.
Queue Commands
queue list
List offline commands queued by nefia exec --when-online.
nefia queue list [--status <state>]| Flag | Type | Default | Description |
|---|---|---|---|
--status | string | pending | Filter by pending, running, completed, failed, expired, cancelled, or all |
Human output shows the queue ID, host, status, truncated command, and expiry timestamp.
queue show
Show details for a queued command.
nefia queue show <id>Displays the full details of a queue entry including ID, host, status, command, timestamps, retry lineage, and execution results (exit code, stdout, stderr) if available.
queue cancel
Cancel a queued command before it runs.
nefia queue cancel <id>queue retry
Create a new pending entry from a failed, expired, or cancelled queue entry.
nefia queue retry <id> [--ttl <duration>]Alias: requeue
| Flag | Type | Default | Description |
|---|---|---|---|
--ttl | duration | 24h | TTL for the new queued retry entry |
The new entry is linked to the original via a retry_of field. The host must still exist in the configuration.
# Retry a failed queue entry with default TTL
nefia queue retry abc123
# Retry with a custom TTL
nefia queue retry abc123 --ttl 48hWebhook Commands
webhook list
List configured webhook destinations from alerts.webhooks.
nefia webhook listwebhook test
Send a test event to every configured webhook.
nefia webhook test [--type <event-type>]| Flag | Type | Default | Description |
|---|---|---|---|
--type | string | test | Event type to send |
webhook send
Send a custom webhook event.
nefia webhook send --type <event-type> --message <text> [--details key=value]| Flag | Type | Default | Description |
|---|---|---|---|
--type | string | required | Event type |
--message | string | required | Event message |
--details | string[] | — | Additional key=value pairs (repeatable) |
Webhook delivery waits up to 30 seconds for completion and returns an error if no webhooks are configured.
Agent Management
agent version
Show the nefia-agent version on remote hosts.
nefia agent version [--target <selector>]Defaults to all if no target is specified. Displays version, compatibility status, and any messages per host.
agent upgrade
Upgrade nefia-agent on remote hosts.
nefia agent upgrade [--target <selector>] [--agent-dir <dir>]| Flag | Type | Default | Description |
|---|---|---|---|
--agent-dir | string | — | Directory containing agent binaries |
Prompts for confirmation before upgrading. Displays old and new version for each host.
agent update
Trigger remote agent self-update via update server.
nefia agent update [--target <selector>] [--version <version>]| Flag | Type | Default | Description |
|---|---|---|---|
--version | string | — | Target version (empty = latest) |
Unlike agent upgrade which pushes a binary from the operator, this command instructs the agent to pull its own update from its configured update server. It enables auto-update in the agent config, optionally sets a pinned version, and restarts the agent service.
# Update agent on a specific host to the latest version
nefia agent update --host my-pc
# Update agent to a specific version
nefia agent update --host my-pc --version v1.2.0agent pin
Pin agent to a specific version on remote hosts.
nefia agent pin <version> [--target <selector>]Sets the pinned_version in the remote agent config. When pinned, the agent's auto-update will only update to the specified version and will not automatically upgrade beyond it.
nefia agent pin v1.2.0 --host my-pc
nefia agent pin v1.2.0 --target allagent unpin
Clear pinned version on remote agents.
nefia agent unpin [--target <selector>]Clears the pinned_version in the remote agent config. The agent's auto-update will resume tracking the latest available version.
nefia agent unpin --host my-pc
nefia agent unpin --target allAudit Commands
audit tail -- Show recent records
nefia audit tail [-n <count>]| Flag | Type | Default | Description |
|---|---|---|---|
-n | int | 200 | Number of records to show |
Displays the most recent audit log entries in a table with sequence number, timestamp, host, operation, job ID, and user.
audit show -- Show records for a job
nefia audit show --job <job-id>Displays all audit records associated with a specific job ID in JSON format.
audit verify -- Verify hash chain
nefia audit verify [date] [--range <range>]| Flag | Type | Default | Description |
|---|---|---|---|
--range | string | — | Date range to verify (e.g. 7d, 30d, 2026-03-01..2026-03-08) |
Verifies the hash chain integrity of an audit log file for a given date (YYYY-MM-DD format). Defaults to today. Verifies both the SHA-256 hash chain and HMAC signatures when the key is available. Use --range to verify multiple dates at once.
audit list -- List audit records with filtering
nefia audit list [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--date | string | today | Specific date (YYYY-MM-DD) |
--range | string | — | Date range (e.g. 7d, 30d, 2026-03-01..2026-03-08) |
--op | string | — | Filter by operation kind |
--host | string | — | Filter by host ID |
--user | string | — | Filter by user |
--limit | int | 100 | Max records to display |
--reverse | boolean | false | Reverse chronological order |
--summary | boolean | false | Human-readable summary format (one line per record) |
Lists audit records with filtering. The --summary flag outputs a human-readable one-line-per-record format: 2024-01-15 10:30:00 | exec | user@host | ls -la | success.
# List today's audit records
nefia audit list
# List records for a specific date
nefia audit list --date 2026-03-01
# Filter by operation type
nefia audit list --op exec --range 7d
# Filter by host and limit results
nefia audit list --host my-pc --limit 50
# Show records in reverse order
nefia audit list --range 30d --reverse
# Human-readable summary
nefia audit list --summarySystem Commands
account
Show account and subscription information.
nefia accountDisplays your plan, status, host count, limits, and cancellation status.
status
Show system status overview with per-host connectivity.
nefia status [--no-check] [--active]| Flag | Type | Default | Description |
|---|---|---|---|
--no-check | boolean | false | Skip connectivity checks for faster output |
--active | boolean | false | Show only online hosts in the host table |
Displays version, config path, VPN status, policy mode, audit status, auth state, host/group/session counts, and a per-host connectivity table.
When VPN is enabled and --no-check is not set, the command creates a standalone VPN tunnel and probes each active host with a TCP dial (3-second timeout, up to 10 concurrent). The host table shows:
Nefia Status Version: 1.0.0 Config: /Users/admin/.config/nefia/nefia.yaml
VPN: enabled (3 active, 1 pending) Policy: enforce Audit: enabled (dir: /Users/admin/.local/state/nefia/audit, today: 42 records) Auth: logged in Hosts: 4 configured Groups: 2 configured Sessions: 1 active
Hosts: ID OS VPN CONNECTION LATENCY my-pc macos active online 12ms office-pc windows active offline - dev-server linux pending - - backup-srv linux active online 45ms
2 online, 1 offline, 1 pending
Use --no-check for fast output without connectivity probing. Use --output json for structured output including a hosts array.
validate
Validate configuration and optionally test host connectivity.
nefia validate [--target <selector>]When a --target is specified, resolves the selector and tests SSH connectivity to each matched host via the VPN tunnel.
bugreport
Generate a sanitized diagnostic bundle for support and debugging.
nefia bugreport [--output-file <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--output-file | string | stdout | Write the report to a file instead of stdout |
The bundle includes system information, sanitized config structure, VPN status, doctor output, and recent audit errors. Private keys, tokens, passwords, SSH keys, API keys, and full command lines are excluded.
update
Check for and apply updates to the Nefia CLI.
nefia update [--check]| Flag | Type | Default | Description |
|---|---|---|---|
--check | boolean | false | Check for updates without applying |
Downloads the latest release, verifies the Ed25519 signature, and atomically replaces the running binary.
backup
Back up configuration and state to a tar.gz archive.
nefia backup [--output <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--output | string | nefia-backup-YYYY-MM-DD.tar.gz | Output archive path |
Archives the configuration file, audit logs, and session state. Sensitive files (keys, tokens, secrets) are automatically excluded.
restore
Restore configuration and state from a backup archive.
nefia restore <archive-path>Extracts files from a backup archive to the config and state directories. Includes Zip Slip protection and skips sensitive files. Prompts for confirmation before restoring.
version
Show version, build, and runtime information.
nefia versionDisplays the nefia version, git commit, build date, Go version, and OS/architecture.
Diagnostics Commands
netcheck
Run compact VPN network diagnostics.
nefia netcheck [--host <id>]| Flag | Type | Default | Description |
|---|---|---|---|
--host | string | — | Limit connectivity tests to a single host |
netcheck is the top-level, discoverable form of nefia vpn diagnose. It summarizes NAT type, STUN reachability, DERP RTTs, TURN/relay availability, route conflicts, and per-host connectivity.
doctor
Run comprehensive system health checks covering configuration, authentication, audit, VPN, and host connectivity.
nefia doctor [--host <id>]| Flag | Type | Default | Description |
|---|---|---|---|
--host | string | — | Check a specific host only |
--strict | boolean | false | Treat warnings as failures (exit non-zero). Useful for CI pipelines |
Similar to brew doctor or tailscale netcheck, this command runs a multi-phase diagnostic suite and reports results as [PASS], [WARN], or [FAIL].
Phases:
- Config -- Verifies the configuration file can be found and loaded
- Auth -- Checks whether the user is logged in
- Audit -- Validates audit logging is enabled and the audit directory is writable
- VPN -- Runs all
vpn diagnosechecks (keypair, port availability, peer validation, STUN, address uniqueness) - Connectivity -- Creates a standalone VPN tunnel and TCP-dials each active host (10 concurrent, 3s timeout)
Nefia Doctor: [PASS] config-path: Configuration found at /Users/admin/.config/nefia/nefia.yaml [PASS] config-load: Configuration loaded successfully [PASS] auth-status: Logged in [PASS] audit-config: Audit logging is enabled [PASS] audit-dir: Audit directory is writable: /Users/admin/.local/state/nefia/audit [PASS] vpn-enabled: VPN is enabled [PASS] operator-keypair: operator keypair is valid [PASS] port-available: UDP port 51820 is available [PASS] enrollment-port: TCP port 19820 (enrollment) is available [PASS] vpn-addr-unique: all 3 VPN addresses are unique [PASS] ssh-identity: SSH public key found in ssh.identities [PASS] stun-reachability: STUN reachable (public IP: 203.0.113.10) [PASS] peer-my-pc-connectivity: Connection OK (12ms) [WARN] peer-office-pc-connectivity: Connection failed: dial timeout
Result: 12 passed, 1 warning, 0 failures
Exit codes:
0-- All checks passed (warnings are allowed)1-- One or more checks failed
Use --output json for structured output with a checks array and summary object.
explain
Look up an error code and display detailed resolution steps.
nefia explain [code] [--list]| Flag | Type | Default | Description |
|---|---|---|---|
--list | boolean | false | List all registered error codes |
Accepts both structured codes (e.g., E2001) and domain codes (e.g., SSH_AUTH_FAILED).
All domain errors in Nefia are produced using the sentinel error pattern (types.Errorf(types.ErrXxx, ...)). The CLI classifies errors via errors.Is() to determine the appropriate exit code and user-facing message. nefia explain displays the resolution steps and documentation links for a given error code.
# Look up a specific error code
nefia explain E2001
# Look up by domain code
nefia explain SSH_AUTH_FAILED
# List all error codes
nefia explain --listError [E2001]: SSH authentication failed
The SSH key or credentials were rejected by the remote host.
Resolution:
- Verify the SSH key: ssh -i ~/.ssh/id_ed25519 <user>@<host>
- Check key file permissions: chmod 600 ~/.ssh/id_ed25519
- Ensure the public key is in the remote host's ~/.ssh/authorized_keys.
- Re-enroll the host if SSH keys were rotated: nefia vpn reinvite --host <host>
Agent Binary
nefia-agent
The nefia-agent binary runs on target PCs and establishes the WireGuard tunnel back to the operator. It is installed during enrollment.
nefia-agent enroll -- Enroll with an invite token
nefia-agent enroll [--token <token> | --token-file <path>] [--install] [--yes]| Flag | Type | Default | Description |
|---|---|---|---|
--token | string | — | Raw invite token from the operator |
--token-file | string | — | Read the invite token from a file |
--install | boolean | false | Install the system service immediately after enrollment |
--out-dir | string | ~/.nefia | Directory used for generated agent.yaml |
--ssh-addr | string | 127.0.0.1:22 | Local SSH server address the agent should expose through the tunnel |
--force | boolean | false | Overwrite an existing agent.yaml without prompting |
--yes | boolean | false | Skip the SSH public-key confirmation prompt |
Enrolls the agent with the operator using the provided invite token. Performs WireGuard key exchange, writes agent.yaml, and can register the system service automatically with --install.
nefia-agent run -- Start the agent
nefia-agent run [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--strict-permissions | boolean | true | Refuse to start if config file has world-readable permissions and contains a plaintext private key |
--auto-update-interval | duration | 0 | Interval for checking binary changes and auto-restarting (0 = disabled, e.g. 5m) |
--log-file | string | platform default | Path to the log file |
--log-max-size | int | 50 | Maximum log file size in megabytes before rotation |
--log-max-backups | int | 5 | Number of rotated log files to retain |
--log-max-age | int | 30 | Maximum number of days to retain rotated log files |
Starts the agent process. Establishes and maintains the WireGuard tunnel, handles SSH forwarding, and reports endpoints to the cloud API.
Default log file locations:
| Platform | Path |
|---|---|
| macOS | ~/Library/Logs/nefia/agent.log |
| Linux | $XDG_STATE_HOME/nefia/agent.log (default: ~/.local/state/nefia/agent.log) |
| Windows | %LOCALAPPDATA%\nefia\logs\agent.log |
Log rotation is handled by lumberjack. When the log file exceeds --log-max-size, it is rotated and compressed. Old files are pruned based on --log-max-backups and --log-max-age.
nefia-agent install-service / uninstall-service / status / wol
nefia-agent install-service
nefia-agent uninstall-service [--yes]
nefia-agent status
nefia-agent wol --mac <mac-address> [--broadcast <ip:port>]| Command | Purpose |
|---|---|
install-service | Register the agent as a platform-native background service (launchd, systemd, or schtasks) |
uninstall-service | Remove the registered service. --yes skips the confirmation prompt |
status | Show the last persisted health report from the agent |
wol | Send a Wake-on-LAN magic packet directly from the agent |
nefia-agent wol is primarily used by nefia power wake through a proxy agent on the same subnet.
DERP Server
nefia-derp
The nefia-derp binary runs a standalone DERP relay server for NAT traversal when direct peer-to-peer connections are not possible.
nefia-derp [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--addr | string | :8443 | Listen address |
--allowed-keys-file | string | — | Path to a file containing allowed WireGuard public keys (one base64 key per line). When set, only listed keys can use the relay. |
--max-clients | int | 10000 | Maximum number of concurrent clients |
--metrics-token | string | — | Bearer token for authenticated /healthz metrics. Without this, /healthz returns basic liveness only. Can also be set via NEFIA_DERP_METRICS_TOKEN environment variable. |
--ping-interval | duration | 30s | Keepalive ping interval |
--trust-proxy | bool | false | Trust Fly-Client-IP / X-Forwarded-For headers for rate limiting. Enable when running behind a reverse proxy. |
--version | bool | false | Print version and exit |
Example:
# Start with ACL and metrics authentication
nefia-derp --addr :8443 --allowed-keys-file /etc/nefia/allowed-keys.txt --metrics-token "secret-token"Advanced Commands
dashboard
Launch the interactive TUI dashboard.
nefia dashboardAlso available by running nefia with no subcommand in a terminal.
daemon
Run the background daemon for scheduled playbook execution and background tasks.
daemon run -- Start the daemon in the foreground
nefia daemon runStarts the Nefia daemon in the foreground. The daemon manages scheduled playbook execution, VPN monitoring, host sync, idle sweep, and key rotation scheduling. Acquires an exclusive PID lock to prevent multiple instances.
Also available as nefia daemon (no subcommand).
daemon install -- Generate platform-specific service configuration
nefia daemon installGenerates a service configuration file for the current platform and prints it to stdout:
- macOS: launchd plist (
~/Library/LaunchAgents/ai.nefia.daemon.plist) - Linux: systemd unit (
~/.config/systemd/user/nefia-daemon.service) - Windows: Task Scheduler (
schtasks) command
mcp serve
Start the MCP (Model Context Protocol) server for AI agent integration.
nefia mcp serveStarts a JSON-RPC 2.0 server over stdio. AI agents like Claude can connect to this server to execute commands and manage files within the policy engine's guardrails. The MCP server hot-reloads configuration changes and starts background VPN monitoring, idle sweep, and host sync.
mcp serve-mtls
Start the MCP server over mTLS TCP.
nefia mcp serve-mtlsStarts the MCP server as a network gateway using mutual TLS authentication instead of stdio. Requires mcp.mtls.enabled: true in configuration (set up via nefia mtls init). Each client connection is authenticated by its client certificate CN, which is used as the agent identity for audit and policy purposes.
docs
Open the documentation site in your default browser.
nefia docs [topic]Available topics are audit, config, exec, fs, mcp, playbook, policy, push, schedule, and vpn. In JSON output mode, the command returns the resolved URL instead of launching a browser.
completion
Generate shell completion scripts.
nefia completion [bash|zsh|fish|powershell]| Flag | Type | Default | Description |
|---|---|---|---|
--install | boolean | false | Install the generated completion file to the standard location |
--path | string | — | Custom installation path (overrides the standard location) |
# Bash (add to ~/.bashrc)
eval "$(nefia completion bash)"
# Zsh (add to ~/.zshrc)
eval "$(nefia completion zsh)"
# Fish
nefia completion fish | source# PowerShell (add to $PROFILE)
nefia completion powershell | Out-String | Invoke-Expressiondevice-lock
Cryptographic device verification for the VPN mesh (Tailnet Lock style). Uses an Ed25519 authority keypair to sign each host's WireGuard public key. Only hosts with a valid, non-revoked signature are permitted to connect when device lock is enabled.
Alias: dl
device-lock init -- Generate authority keypair
nefia device-lock initGenerates a new Ed25519 authority keypair for device lock. The private key is stored in the OS keyring (macOS Keychain, Windows Credential Manager, or file-based fallback on Linux). The public key is stored in the device lock trust store file.
Also sets device_lock.enabled: true and device_lock.mode: log in the config.
device-lock sign -- Sign a host's WireGuard key
nefia device-lock sign <host-id>Signs the specified host's WireGuard public key with the authority key and adds the attestation to the trust store. The host must have an active VPN enrollment with a public key.
device-lock verify -- Verify all hosts' signatures
nefia device-lock verifyVerifies the device lock status of all configured hosts. Each host is classified as trusted, untrusted, pending, or no_vpn.
device-lock revoke -- Revoke a host's attestation
nefia device-lock revoke <host-id>Revokes a host's device attestation. The host will be blocked on the next connection attempt when device lock is in enforce mode. Prompts for confirmation.
device-lock status -- Show device lock status
nefia device-lock statusDisplays device lock status including enabled state, mode (log or enforce), authority key, trusted count, revoked count, and total hosts.
posture
Check device posture compliance against configured policies.
posture check -- Check posture of target hosts
nefia posture check [--target <selector>]Evaluates device posture for target hosts. Displays firewall status, disk encryption status, pass/fail result, and any violations. Defaults to all if no target is specified.
posture policy -- Show current posture policy
nefia posture policyDisplays the current posture policy configuration including enabled state, mode, firewall requirement, and disk encryption requirement.
ssh-ca
Manage the SSH Certificate Authority for short-lived certificate-based authentication.
ssh-ca init -- Initialize SSH CA keypair
nefia ssh-ca initGenerates a new Ed25519 SSH CA keypair. The private key is stored in the OS keyring and the public key is saved to the state directory. Also enables ssh_ca.enabled: true, ssh_ca.auto_sign: true, and sets default certificate durations when unset.
ssh-ca sign-user -- Sign operator SSH key with the CA
Alias: ssh-ca sign
nefia ssh-ca sign-user [--duration <duration>] [--principals <list>]| Flag | Type | Default | Description |
|---|---|---|---|
--duration | string | from config or 24h | Certificate validity duration |
--principals | string | current user | Comma-separated list of principals |
Signs the operator's SSH public key with the CA to produce a short-lived user certificate. The certificate is saved alongside the identity file (e.g., ~/.ssh/id_ed25519-cert.pub).
# Sign with defaults (current user, 24h)
nefia ssh-ca sign-user
# Sign with custom duration and principals
nefia ssh-ca sign-user --duration 8h --principals deploy,adminssh-ca sign-host -- Sign a host SSH public key
nefia ssh-ca sign-host --host <host-id>Reads the host SSH public key and signs a host certificate. The output is written under the state directory by default.
ssh-ca trust-known-hosts -- Add managed CA trust entries
nefia ssh-ca trust-known-hosts [--host <host-id>]Adds managed @cert-authority lines to the operator's known_hosts file so host certificates signed by the SSH CA are accepted.
ssh-ca server-snippet -- Print sshd_config snippet
nefia ssh-ca server-snippet [--host <host-id>] [--os <linux|macos|windows>]Prints the TrustedUserCAKeys, HostKey, and HostCertificate lines to add to sshd_config, along with the recommended reload command.
ssh-ca status -- Show SSH CA status
nefia ssh-ca statusDisplays SSH CA status including initialization state, fingerprint, enabled state, auto-sign setting, cert duration, current user certificate validity, and managed SSH CA trust entries in known_hosts.
mtls
Manage mTLS certificates for the MCP gateway. Uses ECDSA P-256 CA and TLS 1.3.
mtls init -- Initialize mTLS CA and server certificate
nefia mtls init [--hosts <san-list>]| Flag | Type | Default | Description |
|---|---|---|---|
--hosts | string[] | localhost,127.0.0.1 | Server certificate SANs (DNS names or IPs) |
Generates a new ECDSA P-256 CA keypair and server certificate for the MCP mTLS gateway. The CA and certificates are stored in the state directory. Also enables mTLS in the config with listen_addr: 127.0.0.1:19821.
# Initialize with default SANs
nefia mtls init
# Initialize with custom SANs
nefia mtls init --hosts "my-host.local,10.0.0.5"mtls issue-client -- Issue a client certificate
nefia mtls issue-client --name <cn> [--duration <duration>] [--out-dir <dir>]| Flag | Type | Default | Description |
|---|---|---|---|
--name | string | — | Client common name (required) |
--duration | string | 24h | Certificate validity duration |
--out-dir | string | nefia-client-certs | Output directory for certificate files |
Issues a client certificate for an MCP agent. Writes the client cert, key, and CA cert to the output directory.
nefia mtls issue-client --name my-agent
nefia mtls issue-client --name ci-bot --duration 168h --out-dir ./certsmtls status -- Show mTLS CA and certificate status
nefia mtls statusDisplays mTLS CA status including CA common name, expiry, server certificate details, SANs, enabled state, and listen address.
secrets
Manage dynamic credential injection for secret references in commands and playbooks.
secrets list -- List configured secret providers
nefia secrets listLists all configured secret providers with their name and type (e.g., env, file, vault, aws-sm, op).
secrets test -- Test resolving a secret reference
nefia secrets test <reference> [--reveal]| Flag | Type | Default | Description |
|---|---|---|---|
--reveal | boolean | false | Show the resolved secret value (use with caution) |
Tests resolving a secret reference like ${env:MY_VAR} or ${file:key#field}. By default, the resolved value is masked.
nefia secrets test '${env:DATABASE_URL}'
nefia secrets test --reveal '${env:API_KEY}'cluster
Manage HA cluster with leader election and state replication via Raft consensus.
In cluster mode, one node is elected as leader and owns the VPN tunnel. State (sessions, queue) is replicated across all nodes. If the leader fails, a standby node is automatically promoted.
cluster init -- Bootstrap a new cluster
nefia cluster initBootstraps Raft consensus and makes this node the initial leader of a new cluster. Requires cluster.enabled: true in config with node_id and bind_addr set.
# Config prerequisite:
# cluster:
# enabled: true
# node_id: "node-1"
# bind_addr: "0.0.0.0:9700"
nefia cluster initcluster status -- Show cluster status
nefia cluster statusShows cluster status including node ID, Raft state, leader status, and leader ID. Requires the daemon to be running.
cluster members -- List cluster members
nefia cluster membersLists all cluster members with their ID, address, Raft state, and whether they are the local node. Requires the daemon to be running.
cluster add-peer -- Add a peer to the cluster
nefia cluster add-peer --id <node-id> --addr <raft-addr>| Flag | Type | Default | Description |
|---|---|---|---|
--id | string | — | Peer node ID (required) |
--addr | string | — | Peer Raft address, e.g. 10.99.0.2:9700 (required) |
Adds a peer to the cluster. Must be run on the leader node. The peer is persisted to the config file. Requires the daemon to be running.
cluster remove-peer -- Remove a peer from the cluster
nefia cluster remove-peer --id <node-id>| Flag | Type | Default | Description |
|---|---|---|---|
--id | string | — | Peer node ID to remove (required) |
Removes a peer from the cluster. Must be run on the leader node. The peer is also removed from the config file. Requires the daemon to be running.
reactor
View the event-driven automation reactor status and rules.
The reactor runs as part of the daemon (nefia daemon) and receives events from agents via TCP on the VPN interface. Events are matched against rules to trigger automated actions (exec, playbook, alert).
reactor status -- Show configured reactor rules
nefia reactor statusDisplays reactor configuration including enabled state, listen port, and configured rules (name, event pattern, host pattern, action type).
nefia reactor status
nefia reactor status --jsonreactor events -- Show recent reactor events
nefia reactor eventsDisplay recent events processed by the reactor engine. The reactor must be running as part of the daemon (nefia daemon) for events to be available. Events are kept in memory and show the most recent processing activity.
Displays event time, type, host, severity, matched rule, action taken, and any errors.
nefia reactor events
nefia reactor events --jsonaccess
Manage Just-in-Time (JIT) temporary elevated access requests. Requires jit.enabled: true in config.
access request -- Request temporary elevated access
nefia access request --role <role> --hosts <patterns> [--duration <duration>] [--reason <text>]| Flag | Type | Default | Description |
|---|---|---|---|
--role | string | — | Role to request (required) |
--hosts | string | — | Host patterns, comma-separated (required) |
--duration | string | from config or 1h | Access duration (e.g., 1h, 30m) |
--reason | string | — | Reason for access request (may be required by policy) |
Creates a JIT access request in pending status. Must be approved by an admin. When approved, a time-limited grant allows policy-denied operations for the specified role and host patterns.
nefia access request --role admin --hosts "prod-*" --duration 1h --reason "deploy hotfix"
nefia access request --role admin --hosts "web-01,web-02" --duration 30m --reason "debug"access list -- List access requests and grants
nefia access list [--status <state>]| Flag | Type | Default | Description |
|---|---|---|---|
--status | string | — | Filter by status: pending, approved, denied, expired, revoked |
Lists JIT access requests with ID, status, requester, role, hosts, duration, creation time, and expiry.
nefia access list
nefia access list --status pendingaccess approve -- Approve a pending access request
nefia access approve <request-id>Approves a pending JIT access request and creates a time-limited grant. The grant duration was specified when the request was created.
access deny -- Deny a pending access request
nefia access deny <request-id> [--reason <text>]| Flag | Type | Default | Description |
|---|---|---|---|
--reason | string | — | Reason for denial |
Denies a pending JIT access request.
access revoke -- Revoke an active access grant
nefia access revoke <request-id>Revokes a previously approved JIT access grant before it expires.
compliance
Generate advisory compliance reports evaluating Nefia's configuration and audit evidence against common security frameworks. Reports are tools to assist compliance efforts and do not constitute a certification or legal guarantee of compliance.
compliance report -- Generate a compliance report
nefia compliance report --framework <framework> [--period <range>] [--format <fmt>] [--out <path>]| Flag | Type | Default | Description |
|---|---|---|---|
--framework | string | — | Compliance framework: soc2, iso27001, hipaa (required) |
--period | string | 30d | Report period: Nd or YYYY-MM-DD..YYYY-MM-DD |
--format | string | table | Output format: table, json, yaml, html |
--out | string | — | Output file path (required for HTML format) |
Evaluates controls for the specified framework against current configuration and audit evidence. Displays compliance score, control statuses (pass, partial, fail, n/a), and a disclaimer.
nefia compliance report --framework soc2
nefia compliance report --framework iso27001 --period 30d
nefia compliance report --framework hipaa --period 2026-01-01..2026-03-10
nefia compliance report --framework soc2 --format html --out report.htmlverify
Verify binary or SBOM integrity against the signed release manifest.
nefia verify [file] [--self] [--version <version>]| Flag | Type | Default | Description |
|---|---|---|---|
--self | boolean | false | Verify the currently running nefia binary |
--version | string | current build version | Release version to verify against |
Downloads the signed release manifest from GitHub and checks the SHA-256 hash of the specified file against the expected value. The manifest itself is verified with the Ed25519 public key embedded at build time.
# Verify a downloaded binary
nefia verify ./nefia-linux-amd64
# Verify the currently running binary
nefia verify --self
# Verify against a specific version
nefia verify ./nefia-darwin-arm64 --version 1.2.3Related
Complete reference for the nefia.yaml configuration file.
Reference for CLI exit codes and their meanings.
Practical guide to executing commands across multiple hosts.