ZFS, natively
Most tools see mountpoints and stop there. pālana knows which directory is a dataset, plans around the boundaries, and manages the datasets themselves—snapshot to rollback—through the same gate as everything else: a plan you read before Enter.
Boundaries you can see#
In an ordinary file pane, rows sitting exactly on a dataset's mountpoint carry a filled drive mark; a plain filesystem boundary carries a hollow one. That one glyph is the difference between a move that's an instant rename and a move that's 41 GB of copying—which is why the plan names the classification every time.
Z—the dataset tree#
Z flips the focused pane from files to the host's dataset tree —
same pane, same cursor keys, different subject. The header shows a
ZFS chip so you always know which language the pane is speaking.
Mounted datasets are solid; unmounted or legacy ones render dimmed with their
state named—· unmounted, legacy—because grey is
a fact, not a place. ⏎ on a mounted dataset drops you back into
files at its mountpoint. esc or Z leaves the tree.
Entry is straightforward, too: a pane pointed at this Mac gets
no zfs on this Mac, and a host that's never been probed refuses
with the reason rather than showing an empty tree.
Ten verbs, ten plans#
Inside the tree, the verbs change with the subject—ten keys covering the dataset and snapshot lifecycle: create, destroy, rename; snapshot, destroy snapshot, roll back; set and clear the mountpoint; mount and unmount. Every one composes a plan. A snapshot, for instance:
⏎ press enter to run this plan · esc dismisses it zfs · zfs change koan:rpool/sage/koan/cold how: runs locally on the one host involved $ zfs snapshot rpool/sage/koan/cold@before-cleanup $ zfs list -H -o name -t snapshot -- rpool/sage/koan/cold@before-cleanup
The prompts hand you the facts, too: rolling back or destroying a snapshot lists the dataset's actual snapshot names right in the panel, read off the wire, selectable—you copy instead of remembering. Recursive choices are spelled out where you make them: snapshot every child dataset too; roll back past newer snapshots—destroys them; destroy its children and snapshots too—zfs counts both.
Two guardrails hold no matter what. Destroy, by default, makes you type the
word—the word destroy arms the verb—a setting you can turn off
once you trust yourself. And the pool root is out of bounds entirely:
destroy refuses rpool—that is the pool root; pālana manages datasets,
never the pool itself.
Move datasets with send/receive#
When a move's source is a whole dataset and the destination host speaks ZFS, file-by-file transfer is the wrong tool—so the plan reaches for the block-level one:
⏎ press enter to run this plan · esc dismisses it move · move to another machine 1 entry · 412 GB jodo:/tank/sage/jodo/kanyo → koan:/rpool/sage/koan how: zfs send/receive, run host-to-host · using the forwarded ssh key $ zfs snapshot -r tank/sage/jodo/kanyo@palana-20260716-101530 $ zfs send -R -v tank/sage/jodo/kanyo@palana-20260716-101530 | ssh koan 'zfs receive -u rpool/sage/koan/kanyo' runs only after the copy above is verified: $ zfs destroy -r rpool/sage/koan/kanyo@palana-20260716-101530 runs only after the copy above is verified: $ zfs destroy -r tank/sage/jodo/kanyo
The -R carries the dataset's children and their snapshots.
The -v is the
progress bar—send's own cadence, parsed. The receive -u lands
the dataset unmounted, deliberately: on Linux, mounting belongs to
root even when the dataset's verbs are delegated, and a bare receive would
land the data and then fail the mount—an exit code that lies about a
transfer that worked. And the verification behind the gate is shaped for
datasets: not file counts, but the destination answering that
rpool/sage/koan/kanyo now exists.
Mount permissions#
pālana never asks for root it doesn't name. The dataset verbs run under
your own delegation—zfs allow on the datasets you manage. The one
seam is mounting: on Linux it is root's alone, regardless of delegation. So
m mount and u unmount compose with the escalation
visible in the plan—sudo -n zfs mount rpool/sage/koan/cold —
and require passwordless sudo for exactly those two commands. Without the
grant, the refusal includes the reason and an exact sudoers line for the host.
The full explanation—why it is passwordless and optional—is on one page:
the mount grant.
The same seam is woven, visibly, wherever ZFS would mount implicitly: a
mounted dataset being destroyed or re-mountpointed gets a sudo -n zfs
unmount step ahead of the change—in the plan, where you can read it,
never improvised at run time.
The zfs overview#
The zfs… chip on the plan panel's tool strip floats a
one-glance overview—the tree, ages, mount states—deliberately kept to a
glance and a launcher: a glance, nothing more. Z makes the focused pane
the zfs surface. From it, ⇧⌘←/⇧⌘→ point a pane at
the selected dataset. The mutations live in the pane, where the cursor and the
plan panel already are.