User guide / Files and buffers

Directory buffers

Development reference · View source

Open a directory with runyte <directory>, :open <directory>, Space e, or Space E. It becomes an editable buffer: one relative path per line, with / after directories.

docs/
src/
Cargo.toml
README.md

Editing entries

Edit the listing with ordinary modal editing and multiple selections:

EditFilesystem change
Change a nameRename
Delete a lineDelete
Add a lineCreate a file
Add a line ending in /Create a directory
Add docs/roadmap.mdCreate a file inside an existing subdirectory
Change a pathMove
x then y, go to the destination, pCopy
x then d, go to the destination, pMove (cut)
  • Copy and cut work after navigating in the same pane or across split panes. The register keeps the filesystem identity, so pasted entries keep their contents and directories are copied or moved recursively.
  • A pasted cut is applied by writing the destination explorer. Writing the source first is refused, because that would delete the move’s source.
  • Copying within one directory: rename the pasted row before writing.
  • Nothing happens until you write. See Applying changes .

Rows that are not changes:

  • Trailing whitespace and whitespace-only rows are ignored. Writing a listing with only those edits refreshes it to the canonical view.
  • A name ending in whitespace, containing a control character, or not valid UTF-8 cannot be told apart from the row syntax, so such a directory refuses to open as a listing. New rows are held to the same rule before a confirmation opens.
  • A directory cannot be moved below itself: editing dir/ into dir/child is rejected by :w before any confirmation.

Applying changes

:w or :write opens a plan listing every create, rename, move, copy, and delete.

KeyEffect
EnterApply, sending deletions to the operating-system trash
PApply with permanent deletion
EscapeCancel
Arrows, paging, Home, EndScroll the plan

The confirmation shows each reviewed operation and the total.

Before applying, the whole plan is rejected if:

  • the directory’s visible entries changed on disk since it was opened;
  • an entry the plan moves, copies, or deletes changed;
  • anything changed below a directory the plan moves, copies, or deletes (their complete trees are recorded when the plan is prepared).

Activity inside an unaffected child directory does not stale the explorer.

While applying:

  • On Linux, macOS, and Windows, a move, rename, or copy refuses to overwrite an entry that appeared after the plan was checked.
  • Creation and rollback need an empty destination name, even when the competing entry is a dangling symlink.
  • A filesystem without exclusive rename is refused for operations that need it; Runyte never falls back to an overwriting rename.
  • If an operation fails midway, an ERROR notification names it and every operation already applied.

After applying:

  • Other affected clean explorers refresh, and open files follow confirmed renames and moves.
  • Affected explorers with unsaved edits are kept, with a warning.
  • Deleted open paths are reported as stale, not silently redirected.
  • The explorer that applied the plan keeps its edited row order, so a renamed or new entry stays where you wrote it. Entering it again later restores the sorted listing.

What is not guaranteed. These checks prevent destination collisions; they do not make a plan atomic.

  • Earlier operations, including confirmed deletions, may already have completed when a later one fails.
  • Concurrent replacement of a parent or source entry, changes during recursive operations, and native trash path races are outside these guarantees.

Recovering from a failed plan

If rollback finds that an original name was recreated meanwhile, both entries are kept.

  • The ERROR notification gives the original path and the absolute location of the retained original inside a .runyte-move-… staging directory. Failed copy cleanup can likewise leave a .runyte-copy-… directory, also named in the notification.
  • The notification buffer keeps these details after the interaction line moves on, within the notification history and size limits.
  • Staging directories can hold the only remaining copy of a file. Runyte does not delete them on exit or when another plan runs.
  • Inspect both entries before restoring the retained one to a free name, and refresh the explorer before preparing another plan.

Explorer keys

KeyAction
EnterOpen the selected file or directory (the only key that opens; e stays the word-end motion)
- or BackspaceOpen the parent directory and select the child just left
r or Space rRefresh the listing
.Show or hide dotfiles
?Toggle read-only permissions, owner, group, size, and modification-time columns
x y / x d, then pCopy / cut selected entries, then paste in the destination explorer
:w or :writeReview a filesystem plan before applying edits
TabActions, including the ones below and the three display settings
Tab tOpen a terminal in this pane, starting in the shown directory
Tab fOpen the Finder rooted at the shown directory (:open-explorer-finder)
Tab eOpen the shown directory in the system file manager (:open-explorer-system)
Tab sOpen a persistent session here (see Session and destination navigation )

Tab t, Tab f, and Tab e use the directory the explorer shows, not the row under the cursor.

  • Tab t keeps the explorer behind the terminal, with any unsaved edits.
  • Tab e uses xdg-open on Linux and open on macOS. Unapplied edits stay in Runyte; the file manager sees the directory as it is on disk.

Display settings

SettingToggleEffect
editor.show_hidden_files.List dotfiles or leave them out
editor.explorer_details?Show detail columns before each entry
editor.explorer_sort(Tab)The order rows appear in
  • Tab offers all three. They are ordinary settings, so Space o o reaches them too, and a choice here is written to config.yaml: a listing you set up once stays that way next session.
  • A change re-reads every clean explorer, not only the active pane.
  • If the value cannot be saved (no configuration file was loaded, or it uses a construct Runyte will not patch), it still applies to this session and the status line says it was not written.
  • An explorer with unsaved edits refuses a change to dotfiles or order, because re-reading would discard them. Details only prefix existing rows, so ? keeps working.

Details columns show permissions, owner, group, human-readable size, and modification time.

  • They are presentation only; the file name stays the only editable text.
  • Entries from other years show the year instead of the time.
  • In a narrow pane, horizontal scrolling moves through the details first, then the file name, so no column is permanently clipped.

Sort orders. Directories always come first.

ValueOrder
name / name_descendingA to Z / Z to A
modified / modified_descendingOldest / newest first
size / size_descendingSmallest / largest first

A directory’s own size describes how its entries are stored, not how much it holds, so a size order leaves directories in name order. Entries with equal keys keep name order, so nothing shifts between redraws.

Hidden entries and plans. A listing without its dotfiles is planned without them: an entry it never showed is not deleted for being absent, nor reported when it appears. A new name colliding with a hidden one still stops the plan instead of overwriting it.

Symlinks are listed under their own name, followed by a muted → target hint showing exactly what the link stores.

  • The hint is not buffer text: it cannot be selected, edited, or written. Every hint in a listing starts in the same column.
  • Enter opens what the link points at, so you edit the file Git and the language server know about. A broken link says so.
  • Rename, copy, cut, and delete act on the link itself.
  • One explorer per pane. Each pane browses with one explorer, retargeted as it walks. Space b b lists one directory buffer per pane, labelled [explorer] dirname with its project-relative path (. for the project root).
  • Remembered rows. A directory comes back on the row you left. Going to the parent with - or Backspace selects the child just left, so Enter returns to it. If that child is hidden by the dotfile filter, the parent’s remembered row stays selected.
  • Unsaved edits. Retargeting discards the listing, so refreshing or navigating away from unsaved edits asks first.
  • Splitting an explorer works like splitting a file: the new pane shows the same listing on the same row. Navigate it elsewhere and it gets an explorer of its own, which is how copy and cut across two explorers work.
  • Closing an explorer retires its buffer and keeps every pane. Each pane returns to its most recently used live buffer, then any live buffer, or a scratch buffer. :c refuses unapplied edits; :c! drops the plan without touching the filesystem.

Changes made outside Runyte

An explorer is watched like an ordinary file. When another process adds, removes, or renames an entry directly in its directory, every pane showing it gains [STALE].

  • The listing is left alone: rows, selections, unsaved renames, and undo history survive, since replacing them would discard edits not yet written.
  • A clean explorer attached to no pane refreshes automatically when brought back into a pane. Unapplied edits are preserved and still require an explicit refresh.
  • Space r or :reload re-reads the directory and clears the marker. So does navigating elsewhere or writing a plan.
  • Entries hidden by the dotfile filter are not compared, so their changes go unnoticed too.

Names on Windows

  • Reserved device names, alternate data stream syntax, trailing spaces or dots, and names differing only in case are rejected.
  • Renaming one entry by changing its case is supported.
  • Moves between volumes are refused before staging. Copy, check the copy, then delete the source.
  • Quoted command paths keep literal backslashes, including UNC roots and a trailing separator: :open "C:\work files\note.txt".