Start here
Strata is a fast, keyboard-first GTK file manager for Linux. It is built for Arch Linux and Omarchy, and may also run on other x86_64 or aarch64 Linux systems with GTK 4.12 or newer and glibc 2.39 or newer.
Install
Run this in a terminal as your normal user, not root:
curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh | bash
The installer walks you through five steps:
- It checks your machine: x86_64 or aarch64, glibc 2.39 or newer, and whether you run Omarchy.
- On Arch-based systems, including Omarchy, it lists the missing packages and
asks before running
sudo pacman. It then offers optional SMB share and camera RAW support. On other distributions, it lists the libraries to install and stops unless you confirm they are installed. - It downloads the latest stable release and checks its SHA-256 checksum before
extracting it. With a logged-in
gh, it also verifies the build's provenance. - It installs the binary to
~/.local/bin/strata. - It asks about optional extras: a launcher entry, then making Strata the default for folders, "Open file location" from other apps, the system file chooser, and Omarchy keybinds. On Omarchy or other Arch-based systems with udiskie, it also offers to unlock encrypted drives with Strata. Only the launcher entry defaults to Yes. The folder question follows only a Yes to the launcher entry, and a Yes to it sets up "Open file location" without asking. Answer No to the keybinds unless you run Omarchy: elsewhere, Yes stops the installer with an error.
If the summary warns that ~/.local/bin is not on PATH, add it in your shell
configuration, or start Strata from your launcher.
First launch
Start Strata from your launcher, or run:
strata
Strata opens your home folder in Columns view. Each folder you open adds a column to the right, so the path you took stays visible. The sidebar lists Home, Trash, Network, and your standard folders. Folders you pin appear under PINNED, and drives under DEVICES. On Omarchy Quattro, Strata follows your desktop theme; otherwise it starts in Tokyo Night.
Try these three things first:
- Switch views. Press Ctrl+1 for Columns, Ctrl+2 for Icons, and Ctrl+3 for List. Strata remembers your choice.
- Preview a file. Click an image or text file, or select it and press Space. Press Space again to close the preview. Double-click opens it.
- Search everywhere. Press Ctrl+K and type part of a name. Search covers your home folder and mounted local drives, wherever you are.
Forgot a key? Press F1, or click F1 Shortcuts in the footer, to search every shortcut. Ctrl+, opens Settings.
Where to go next
- Install and integrate: unattended installs, default file manager, system file chooser, and updates.
- Views: Columns, Icons, and List, sorting, and per-folder settings.
- Keyboard: the shortcuts worth learning and how to look up the rest.
- Find files: filter a folder or search everywhere.
- Previews: the preview panel, quick looks, media, and documents.
- Everyday operations: copy, move, rename, trash, undo, archives, and jobs.
- Custom actions: add your own scripts to the right-click menu.
- Themes: bundled themes, Omarchy, and your own colors.
- Settings: where settings live and which to change.
- Remote and devices: SMB, SFTP, phones, cameras, and drives.
- 10xer mode: a Yazi-style key map for keyboard-only work.
Full detail: Installation and desktop integration covers every installer option, manual installation, and uninstalling.
Install and integrate
Install Strata with one command, then choose how much of your desktop it takes over. Every integration is opt-in and reversible.
Install interactively or unattended
Run the installer as your normal user:
curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh | bash
It needs x86_64 or aarch64 and glibc 2.39 or newer. On Arch and Omarchy it
installs missing packages with sudo pacman. On other distributions it lists
the libraries to install yourself, then asks you to confirm. It verifies the
latest stable release's checksum, installs it to ~/.local/bin/strata, then
asks about each integration:
| Question | Default | Flag |
|---|---|---|
| Add Strata to your desktop application menu? | Yes | --with-desktop-entry |
| Make Strata the default application for opening folders? | No | --with-folder-association |
| Use Strata for "Open file location" from other applications? | No | --with-file-manager |
| Replace your current Open/Save chooser with Strata in portal-aware apps? | No | --with-file-chooser |
| Replace Omarchy's Nautilus file-manager keybinds with Strata? | No | --with-omarchy-keybinds |
The folder question follows only a Yes to the menu entry, and a Yes to it also sets up "Open file location". Answer No to the keybinds unless you run Omarchy.
On Arch or Omarchy, to install without questions, pass the flags for the
integrations you want. Anything you leave out stays off, except that
--with-folder-association also turns on the menu entry and "Open file
location":
curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh \
| bash -s -- --with-desktop-entry --with-file-manager
Unattended package installs need passwordless sudo or cached credentials.
--help lists every flag. Unattended mode refuses to replace an existing
binary, so to add an integration later, rerun the installer without flags and
answer Yes to replacing it.
Run ~/.local/bin/strata --version to confirm the install. If the installer
warns that ~/.local/bin is not on PATH, add it to run strata by name.
AUR packages are not yet published; use the installer.
Add Strata to your launcher
The desktop menu entry puts Strata in your launcher. The installer writes
~/.local/share/applications/io.github.lgse.Strata.desktop and the icon under
~/.local/share/icons/hicolor. To add it by hand, see
Desktop entry.
Make Strata the default file manager
With the launcher entry installed, press Ctrl+, and open Settings → General. The System file manager row lists Open and Save dialogs, Opening folders, Reveal in File Manager, and, on Omarchy, Keyboard shortcuts. Close any open file dialogs, then click Complete setup to configure all of them. On Omarchy, Super+Shift+F and Super+Alt+Shift+F then open Strata instead of Nautilus. Restore default undoes it.
To set these up by hand, see Usage and desktop integration.
Use Strata as the system file chooser
Strata can draw portal Open and Save dialogs for local files. Complete setup in Settings → General turns this on with the rest of the row. Your current chooser stays listed as the fallback, and Restore default brings it back.
To switch only the chooser by hand, see Per-user installation.
Keep Strata up to date
Strata checks for a newer release automatically. When one exists, an Update available notice appears in the sidebar. Click it to read the release notes, then click Download update. You can also open Settings → Updates and click Check now or Install update.
Strata verifies the release's signature, replaces the binary, and restarts. If the new build fails to start, it restores the previous one.
To try builds early, set Release channel in Settings → Updates from Stable to Preview (alpha, beta, and release candidates) or Nightly (daily builds). Switching a prerelease install back to Stable offers Return to stable.
When a package manager installed Strata, Strata never replaces itself. It offers Open Omarchy Update, Open AUR Update (View on AUR without an AUR helper), or tells you to run a full system update.
Full detail: Installation and desktop integration, System file chooser, Signed updates
Views
Show any folder as Columns, Icons, or List, and switch with one key. Sort each folder its own way, and set the text size for the whole app.
Switch between Columns, Icons, and List
| Press | View | What you get |
|---|---|---|
| Ctrl+1 | Columns | One column per open folder, so the whole path stays visible. The default. |
| Ctrl+2 | Icons | A grid of thumbnails, with size, dimensions, duration, or item count under each name. |
| Ctrl+3 | List | A table with Name, Mode, Size, Type, and Modified columns. |
Or click Appearance in the window header and pick a view under VIEW. Switching keeps your folder, selection, and filter. Strata reopens in the view you used last.
In Columns, click a folder to open it as the next column. Drag a column's right edge to resize it. When you let go, the window's other open columns match that width, and new columns open at it. Double-click the edge to fit one column to its contents.
In Icons, click Thumbnail size in the pane header and drag the slider between 32 and 256 px.
Sort a folder
- Columns and Icons: click Choose sort field in the pane header and pick Name, Size, Modified, or Type. The arrow button beside it reverses the order.
- List: click the Name, Size, Type, or Modified heading to sort by it. Click it again to reverse.
Name sorting ignores case and reads numbers by value, so File 2 comes before
File 10. Folders first, in the Columns and Icons sort menu, is on by
default and keeps folders ahead of files in both directions, in every view.
Keep settings per folder
Each local folder remembers the sort you choose in it and its Icons thumbnail
size. Remote shares, Trash, and Recent do not.
Sort ~/Downloads by Modified, descending, and only ~/Downloads changes,
even after a restart. Other folders keep the default.
Once a folder has its own sort, its sort menu in Columns or Icons offers Make this the default sort and Reset to default sort. Once you move a folder's thumbnail slider off the default, the popover offers Make this the default size and Reset to default size.
Press Ctrl+, and open General. Under BROWSING you find:
- Remember sort and icon size per folder, on by default. Turn it off and the last sort you choose becomes the default for later folders.
- Default sort, a field and a direction, Name ascending at first.
- Forget all folder settings, whose Clear button returns every folder to the defaults.
Change the text size
| Press | Effect |
|---|---|
| Ctrl++ or Ctrl+= | 1 px larger |
| Ctrl+− | 1 px smaller |
| Ctrl+0 | Back to 13 px |
| Ctrl+wheel | 1 px per notch |
The Appearance menu has the same buttons under TEXT SIZE; the middle one shows the current size and resets it. To type a size from 8 to 48, use Text size in Settings → Appearance. Every window follows at once.
Good to know
- In Icons and List, going back to a folder restores its selection and scroll position. In Columns, going back up selects the folder you came from.
- Group by file type in the Appearance menu groups List rows under headings such as Folder and JSON document. It works only in List.
- Per-folder values live in
~/.local/state/strata/folder-views.toml, not insettings.tomlor in the folders themselves. - A subfolder does not inherit its parent's sort or size.
- Ctrl+wheel over a PDF preview zooms the PDF instead of the text. Text size never changes thumbnail size or preview zoom.
Full detail: Returning to a visited directory in the Keyboard navigation reference.
Keyboard
Run Strata without touching the mouse. Learn the keys below, press F1 when you forget one, and use the arrows to move between files, the sidebar, and the top navigation bar.
Shortcuts worth memorizing
| Keys | What it does |
|---|---|
| F1 | Show or hide the shortcut reference |
| Ctrl+K | Open global search |
| Ctrl+F | Filter the current pane |
| Ctrl+L | Edit the location |
| Enter | Open the current item |
| Space | Preview a file, or open a folder |
| Alt+Left / Alt+Right | Back / forward in history |
| Alt+Up | Go to the parent folder |
| Ctrl+C / Ctrl+X / Ctrl+V | Copy, cut, paste |
| Ctrl+Z / Ctrl+Shift+Z | Undo / redo the last file operation |
| F2 | Rename |
| Delete / Shift+Delete | Move to Trash / delete permanently |
| Ctrl+1 / Ctrl+2 / Ctrl+3 | Switch to Columns, Icons, or List |
| Ctrl+T / Ctrl+W | New tab / close the active tab |
Look up any shortcut
- Press F1, or click F1 Shortcuts at the bottom left of the window.
- Type into Search actions or keys…:
renamefinds F2, andctrl+kfinds global search. - Press F1 or Escape to close it. Focus returns where it was.
The list shows only the keys that work in the current view.
Move through views
Plain arrows move focus. In Icons and List they never change directory.
- Columns: Up and Down move through a column. Right enters the folder, Left goes back to the parent column. Right never opens a file; press Enter to open it. If the file's preview is showing, Right moves focus into it.
- Icons: arrows move one tile in that direction.
- List: Up and Down move through rows.
Keep going past the edge to reach the rest of the window:
- Up from the first item focuses the pane header. Left and Right move between its buttons, Enter or Space presses one, and Down returns to your file.
- Left focuses the sidebar: from the left edge in Icons, any row in List, or the first column in Columns. Up and Down move between places, and Right returns to the files.
- Up from the top of the sidebar reaches the top navigation bar.
Home and End jump to the first and last item, and Page Up and Page Down move one page. Tab leaves the file list in one press, and Shift+Tab back into it lands on the item you left.
To find a file by name, start typing: Type to search, on by default,
opens the pane filter with what you typed and shows only matching items (see
Find files). Turn it off in Settings → General and h, j,
k, l act as Left, Down, Up, Right instead.
Good to know
- Shortcuts work on any keyboard layout and ignore Caps Lock. On Russian, Ctrl+C is the key that types с. Digits count by position, so Ctrl+1 works on AZERTY without Shift.
- Turn on Keep arrows in file list in Settings → General to stop arrows leaving the files. Ctrl+\ toggles it, and Ctrl+Shift+B jumps to the sidebar.
- Hide the F1 Shortcuts button with Show F1 Shortcuts button in Settings → General. F1 still opens the reference.
- In 10xer mode (Ctrl+Shift+M) the keys change, and F1 lists only the 10xer keys.
Full detail: the Keyboard navigation reference covers every key, view, and focus rule.
Find files
Press Ctrl+F to narrow the folder you are looking at. Press Ctrl+K to search Home and every mounted local drive, from any folder.
Filter the current folder
- Open a folder and press Ctrl+F, or click the funnel button in the pane.
- Type part of a name, such as
invoice. - Press Down to reach the results, then Enter to open one.
- Press Escape to get the full listing back.
You can skip Ctrl+F. With Type to search on, the default, start typing in
a file view and the filter opens with what you typed. Press / to open an
empty filter.
The filter searches the current folder and its subfolders, showing each subfolder result's path below its name. Queries match names only, ignoring case.
| Query | Finds |
|---|---|
invoice | Any name containing invoice. |
trahs | strata-trash.svg. Queries of 4 or more letters and digits forgive one typo. |
*.pdf | Names ending in .pdf. |
IMG*.MOV | Names starting with IMG and ending in .MOV. |
* is the only wildcard; ? and [] match themselves.
Results act like normal items: drag them, copy them, or right-click for the item menu. Space previews the selected file.
Search everywhere
- Press Ctrl+K, or click the search button in the header.
- Type a name or a piece of a path, such as
cat-01. - Press Up and Down to pick a result, then Enter, or click it, to open it.
Matching is fuzzy: the characters you type must appear in order, in the name or
the path. cat-01 lists cat-01-photo.jpg first, and
bucket-cat/file-01-noise.jpg below it.
- Opening a folder goes into that folder.
- Opening a file shows it selected in its folder, with quick preview open.
- Alt+Enter, or right-click → Open containing folder, opens the result's parent folder with the result selected.
Press Escape, or Ctrl+K again, to close search.
Search indexes Home and every mounted local drive, but skips:
- hidden files and folders, unless hidden files are shown (Ctrl+H);
- generated trees such as
node_modules/,target/,.venv/,.cache/,__pycache__/, andgo/pkg/mod/; - anything a
.gitignoreor.ignorefile excludes; - folders you exclude yourself.
Choose what search skips
Keep a large or private folder out of Ctrl+K results:
- Press Ctrl+, to open Settings, and choose General.
- Under SEARCH & FILTERING, find Global search exclusions.
- Type a rule, or click Browse… to pick a folder.
- Press Enter or click Add.
A rule is a folder name or a directory path:
| Rule | Skips |
|---|---|
build | Every folder named build, in any case, and everything inside it. |
~/LargeData | That one folder and everything below it. |
A rule containing / is a path and must start with / or ~/, so
project/build is refused. A folder name is matched literally, with no
wildcards. Changes apply the next time you open Ctrl+K. To delete a rule,
click the remove button beside it.
Good to know
- Exclusions apply to Ctrl+K only. The Ctrl+F filter still finds files inside excluded folders.
- Ctrl+K does not search remote shares. Inside a share, Ctrl+F narrows the loaded listing without searching subfolders.
- Ctrl+K shows at most 100 results. On a very large disk, indexing stops early and the footer shows Partial results; excluding big folders helps.
- In Settings → General, turn off Include subfolders to filter only the current folder, or turn on Open search results directly to launch files from Ctrl+K instead of previewing them.
- In 10xer mode, press
fto filter andsto search subfolders instead of Ctrl+F.
Full detail: the Keyboard navigation reference covers filter patterns, filter focus, and Ctrl+K keys.
Previews
See inside a file without opening it. Strata previews text, code, images, PDFs, documents, spreadsheets, audio, and video in a panel beside your files.
Show the preview panel
In Columns, the default view, the panel is already on. It holds a slot right of your columns, so previews never move them. In Icons and List it starts hidden: click the view button in the header bar (your current view's icon, tooltip Appearance) and click Preview panel. Clicking it again hides the panel in any view.
Drag the divider to resize the panel; the width lasts until you close the window. When the window gets too narrow, the preview hides and media pauses. Widen the window and it returns.
Take a quick look
Click a supported file and its preview opens; Single-click file previews is on by default. In Columns, arrowing onto a file opens its preview too. Space toggles the preview: press it to close the preview, and again to reopen it for the focused file.
- Menu. Right-click a file and choose Quick preview.
- Follow. With the preview open, arrow to another file and the preview follows.
- Step inside. In List or Columns, press Right to move focus into the preview. Ctrl+C then copies selected text, not files.
Space on a folder opens the folder instead.
Peek into a folder
Turn on Settings → General → BROWSING → Folder peeking; it is off by default. Rest the pointer on a folder in Icons or List for half a second, and a popover lists up to eight of its entries. Columns never peeks.
Play media and read documents
Audio, video, and GIF previews open paused. To start them at once, turn on Settings → General → BROWSING → Autoplay media previews.
| Keys | Action |
|---|---|
| Ctrl+Alt+Space | Play or pause |
| Ctrl+Alt+Left, Ctrl+Alt+Right | Seek 5 seconds |
| Ctrl+Alt+Up, Ctrl+Alt+Down | Volume up or down |
| Ctrl+Alt+M | Mute |
| Ctrl+Alt+<, Ctrl+Alt+> | Previous or next file of the same type |
Audio shows cover art, tags, a live spectrum, and a waveform you click to seek. On a video, press Enter to continue in your default player; mpv, VLC, Celluloid, and MPlayer pick up where the preview stopped.
Local Markdown, HTML, RTF, CSV, and TSV files open rendered. Click View source in the header for the raw text, and View rendered to go back. To start in source, turn off Render documents by default in the same BROWSING group. Local XLS, XLSX, and ODS files show their first sheet as a sortable table, and local DOCX files render too.
To search a preview:
- Move focus into the preview and press Ctrl+F, or click Find in preview.
- Type your text. Case is ignored.
- Press Enter for the next match, Shift+Enter for the previous.
- Press Escape to close find. The match stays selected for Ctrl+C.
Find skips rendered tables, PDFs, and media. With focus in the file list, Ctrl+F filters filenames instead.
Why previews are sandboxed
A file can be crafted to attack the program that reads it. So Strata decodes images, RAW photos, PDFs, XLS, XLSX, and ODS workbooks, DOCX, and media in a helper process inside Bubblewrap. The helper sees only that one file, has no network, and is killed when you move on. Plain text is read directly, up to the first 1 MiB.
If Bubblewrap is missing, these previews show Preview unavailable; Strata
never decodes them outside the sandbox. Install your distribution's
bubblewrap package.
Full detail: Document previews, Preview sandbox, and Keyboard navigation.
Everyday operations
Copy, move, rename, and delete files with familiar keys, and press Ctrl+Z when something goes wrong.
Copy, move, and paste
- Select files and press Ctrl+C to copy or Ctrl+X to cut. Cut items show scissors.
- Go to the destination and press Ctrl+V.
With exactly one folder selected, Ctrl+V pastes into it. Otherwise it pastes
into the folder you are viewing. A copy pasted into its own folder becomes
report (1).pdf; Ctrl+D (Duplicate) does this without the clipboard.
Prefer a dialog? Right-click and choose Move to… or Copy to….
When a name is taken, File already exists offers:
- Replace: overwrite that item.
- Keep Both (copies only): add
name (1).extbeside it. - Merge (folder copied onto folder): add the incoming contents, replacing same-named files.
- Skip (several items): keep the existing item, transfer the rest.
- Cancel: transfer nothing.
Apply to All reuses your answer for the remaining conflicts.
Create and rename
Press Ctrl+Shift+N for a new folder, type its name, and press Enter. Right-click empty space for New Folder or New File. Ctrl+Alt+N (New Folder with Selection) moves the selected items into a new folder.
To rename, press F2 or Ctrl+R, or click the name of a single selected item again after a pause. Enter, Tab, or clicking elsewhere saves; Escape keeps the old name.
Trash, restore, and delete
Press Delete to move the selection to Trash, with no prompt. To get it back later, open Trash in the sidebar, right-click the item, and choose Restore. Strata shows the original path before restoring.
Press Shift+Delete, or choose Permanently delete, to delete for good after a confirmation. This cannot be undone.
Good to know:
- Inside Trash, Delete always deletes permanently, after confirming.
- Locations without Trash, such as
/dev/shm, ask before deleting permanently.
Undo a mistake
Press Ctrl+Z to undo the last file operation; Ctrl+Shift+Z or Ctrl+Y redoes it.
| You did | Ctrl+Z |
|---|---|
| Move, cut, or Trash | Puts items back |
| Copy | Trashes the copies |
| Rename | Restores the old name |
| New folder or file | Trashes it |
The history holds 32 operations, shared by every window.
Work with archives
Right-click an archive and choose Extract here or Extract to…, or
double-click it. A single top-level entry lands under its own name. Several land
in a folder named after the archive, such as photos/ for photos.zip.
Nothing existing is overwritten.
To create one, select items and choose Compress…. Pick ZIP, 7Z, TAR.GZ, or TAR; ZIP and 7Z can be Password protected.
Drag and drop
Drop items onto a folder, a sidebar place, or a parent breadcrumb.
| Drop | Result |
|---|---|
| Same drive | Move |
| Another drive | Copy or move? asks |
| Holding Ctrl | Copy |
| Holding Shift | Move |
Hover over a folder for 750 ms to open it mid-drag. To skip the question, set Settings → General → FILE TRANSFERS → Drag & drop to another device to Always copy or Always move.
Follow progress in Jobs
A file operation that runs past 350 ms, or touches 16 or more items, shows its progress. Copies, deletions, and compression get a card in the bottom-right corner, so you can keep browsing; the card's X cancels it. Moves, extraction, and restores show a progress dialog; Cancel stops them. Either way, what is already done stays done.
Custom actions run in the background and open Jobs. Reopen it
from the footer button, such as 1 job running. Details shows a job's
output; Cancel stops it. Escape hides Jobs without stopping anything.
Full detail: Archives reference, Creating files and folders, and Jobs and cancellation
Custom actions
Add your own scripts to the right-click menu. An action is a folder with a
small action.toml and, usually, one script. Strata runs it in the background
and shows its progress and output in the Jobs dashboard.
Your first action
- Open Settings → Actions and click New action….
- On General, type
Count linesin Name. Leave Id blank; Strata derivescount-linesfrom the name. - On Script, click Library and pick Count lines. This Bash
recipe needs only
wcand offers the action only for text files such as.txtand.md. - Click Create action.
- Select a few
.txtor.mdfiles, right-click, and choose Actions → Count lines.
The Jobs dashboard opens with the new job. Click the eye button (Details) on the job to read each file's count and the total.
What is on disk
Settings wrote this, and you can edit it by hand:
~/.config/strata/actions/count-lines/
action.toml
run.sh
The folder name must match the id. A short working manifest is:
schema_version = 1
id = "count-lines"
name = "Count lines"
icon = "file-code"
[when]
kinds = ["file"]
[run]
runtime = "bash"
entrypoint = "run.sh"
The [when] table decides when the action shows up. Add
extensions = ["md", "txt"] to limit it to those files, or set
kinds = ["folder"] for folders. The action appears only when every selected
item matches. The menu rereads your files each time it opens, so a hand edit
shows up on your next right-click. If you opened Settings → Actions since
Strata started, restart Strata first.
Writing a script in Python
Python actions can import a helper with no pip install. This script converts
each selected image to WebP beside the original:
#!/usr/bin/env python3
import subprocess
from strata_actions import context, require_tool
ctx = context()
magick = require_tool("magick")
for index, path in enumerate(ctx.paths, start=1):
target = f"{path}.webp"
subprocess.run([magick, path, target], check=True)
ctx.progress(index, ctx.count, "Converting images")
ctx.output(target)
A new action starts as Python with main.py and a starter script;
replace the starter with this one. On Behavior, clear Folders and set
Extensions to png, jpg, jpeg. In the manifest that is runtime = "python"
and entrypoint = "main.py".
ctx.paths holds the selected absolute paths, ctx.progress fills the
progress bar, and ctx.output records where a result went. require_tool
stops the run when a program is missing, and any non-zero exit marks the job
failed.
Running an existing program instead
Choose Command under Runtime, name the Program, and enter one
argument per line under Arguments. On Behavior, clear Folders and
set Extensions to jpg, jpeg, png. In the manifest:
[when]
kinds = ["file"]
extensions = ["jpg", "jpeg", "png"]
[run]
runtime = "command"
program = "magick"
args = ["mogrify", "-resize", "1024x1024>", "{paths}"]
confirm = true
{paths} expands to every selected file, one argument each, and nothing goes
through a shell.
mogrify overwrites the originals, so confirm = true asks before running.
In Settings that is the Confirm switch on Behavior.
Good to know
- Actions run with your permissions and no sandbox. Read a recipe before you save it. Actions you add with Import… arrive disabled.
mode = "per-item"runs the action once per file. Use{path}there instead of{paths}.- In 10xer mode, press
;then1–9or0to run one of the first ten matching actions. - Actions are not offered in Trash or on remote locations.
- A manifest that fails to load is listed under PROBLEMS in Settings → Actions with the reason. Your other actions still load.
Full detail: the Custom actions reference covers every manifest field, environment variable, and recipe.
Themes
Strata ships 95 themes, follows your Omarchy theme if you have one, and reads your own theme files. Changes restyle every open window at once, including menus, dialogs, and code previews.
Pick a bundled theme
Press Ctrl+, and open Appearance. On Omarchy, first turn off Follow Omarchy under THEME; while it is on, the library is greyed out. In THEME LIBRARY, type in Search themes or pick Light or Dark, then click a card. The theme applies at once, the card gets a check, and Strata remembers it after a restart.
Without Omarchy Quattro, a fresh install starts with Tokyo Night.
Follow Omarchy
On Omarchy Quattro, a fresh install follows your desktop theme. The Follow Omarchy
switch sits under THEME on the same page. Strata reads the active theme from
~/.local/state/omarchy/current/ and restyles itself whenever you switch
Omarchy themes or edit colors.toml, with no restart.
Omarchy variant sets how Strata reads the palette:
- Original, the default, maps the palette as it is.
- Darker draws near-black surfaces from the terminal background. Light palettes turn dark too.
- High contrast raises text and border contrast and keeps a light palette light.
Write your own theme
A theme is a TOML file with a name and nine colors. Create the themes folder:
mkdir -p ~/.config/strata/themes
Then save this as ~/.config/strata/themes/ocean-blue.toml:
name = "Ocean Blue"
background = "#0c1a2b"
surface = "#122438"
text = "#c9deed"
accent = "#4fd6ff"
danger = "#ff6b7a"
muted = "#1e3a52"
highlight = "#244d68"
border = "#315b75"
dim_text = "#6f8da3"
Restart Strata. Your theme appears in the library after the bundled ones; click
its card to use it. On Omarchy, turn off Follow Omarchy first. Colors can
be hex (#rgb, #rrggbb, or #rrggbbaa for translucency), rgb(), or a color
name. A file with a missing key or an invalid color is skipped without a
message, so check the file if your theme is missing. danger is the one color
you may leave out.
You do not have to write the file by hand. Click Add theme below the
library. The Add a theme panel opens with a name field and a picker for
each color, seeded from your current theme. Every change previews live;
Cancel puts your theme back. Click Add theme to save the file and
switch to it, no restart needed. The file is named after the theme: Ocean Blue saves as ocean-blue.toml, or ocean-blue-2.toml if that file exists.
Syntax colors for code previews
Add any of these five keys to a theme file, then restart Strata, to tune code previews:
syntax_keyword = "#ff7b72"
syntax_string = "#7ee787"
syntax_constant = "#79c0ff"
syntax_type = "#ffa657"
syntax_preprocessor = "#d2a8ff"
A key you leave out keeps a color derived from your accent and text. Comments
use dim_text, and Markdown headings use accent. The Add a theme panel has
a picker for each of the five roles. Every bundled theme brings its own syntax
colors, and following Omarchy takes them from the Omarchy palette.
Good to know
- Name a file after a bundled theme id, such as
dracula.toml, and yours replaces the bundled one. Saving from the panel never does this: it picks a free name such asdracula-2.toml. - Interface icons draw in the accent. Icons for code and config files keep their own colors; set File icon colors to Theme colors to tint them too.
- You can restyle Strata in
~/.config/gtk-4.0/gtk.css; its colors are named@strata_bg,@strata_accent, and so on.
Full detail: the Themes reference covers the Base16 mapping, GTK CSS precedence, and the Omarchy color mapping.
Settings
Change how Strata looks and behaves from one panel, and keep most settings in one TOML file you can track with your dotfiles.
Open Settings
Press Ctrl+, or click the gear (Settings) in the window header. The panel first opens on General; the other pages are Appearance, Actions, Updates, and About.
Type in Search settings to jump to a row: "font" finds Text size. Escape clears the search; press it again, or click outside the panel, to close Settings.
Find settings.toml
Every preference change is saved at once to ~/.config/strata/settings.toml, or
$XDG_CONFIG_HOME/strata/settings.toml when you set that variable. A fresh
install has no file until your first change.
To edit it by hand, close every Strata window, change values in place (a key written twice makes the file invalid), and reopen Strata:
language = "fr"
date_format = "iso"
show_hidden = true
Keep settings in your dotfiles
Change any setting once so the file exists. Then close Strata, move the file into your repository, and link it back:
mkdir -p ~/dotfiles/strata
mv ~/.config/strata/settings.toml ~/dotfiles/strata/settings.toml
ln -s ~/dotfiles/strata/settings.toml ~/.config/strata/settings.toml
On another machine, close Strata and remove any ~/.config/strata/settings.toml
there. Then run mkdir -p ~/.config/strata and the same ln -s line.
Strata writes through the link and keeps the file's permissions. The link and
the file must both be yours, and the file must exist.
Strata loads the file at startup. Pull dotfiles changes while Strata is closed: a change made in a running Strata saves its own copy of every setting over them.
Link the file, not ~/.config/strata: tabs.toml there changes as you work.
Custom themes live in its themes/ folder; link that too. Otherwise a missing
custom theme falls back to Azure Glow, and your next change saves that into your
dotfiles. Copy custom actions into actions/ rather than linking it: Strata
cannot create, edit, import, or toggle an action in a linked actions/.
Settings worth changing
Language
General → Language offers Auto-detect, which follows your system language, and 11 languages listed by their own names, such as Français. Click Restart now to apply the change. Japanese, Korean, and Chinese need a CJK font such as Noto Sans CJK.
In the file, write language = "auto" or a code: en, fr, de, es, it,
pt-BR, ru, vi, ja, ko, or zh-CN.
Modified date format
General → Modified date format sets how file times read in lists and previews.
| Choice | Looks like | date_format = |
|---|---|---|
| Relative (default) | "Just now", "5m ago", "Monday", "2w ago" | "relative" |
| ISO 8601 | 2026-09-17 14:30 | "iso" |
| Long | "September 17, 2026, 14:30" | "long" |
Where new windows open
Under General → Default directory, click Home directory and pick a folder. A new window opens there unless it has a folder to open or tabs to restore; turn off Restore open tabs to always start there. Reset returns to home.
Hidden files
Press Ctrl+H or Ctrl+. to show or hide hidden files in every window. Strata remembers the choice.
Good to know
- A change in one window applies to every open window at once, except Language and Appearance → Interface renderer, which wait for a restart.
- Opening Settings never writes to
settings.toml; only a change does. - A bad value, such as
show_hidden = "yes", falls back to its default alone. - If the file is not valid TOML, Strata starts with defaults and never saves over it. Your first change shows Settings file can't be read. Fix the file and restart Strata.
- If a save fails, Settings can't be saved appears. Changes last until Strata closes; each new change retries the save.
Full detail: the Themes reference covers Appearance; Browser tabs covers Restore open tabs.
Remote and devices
Open network shares, SFTP servers, phones, cameras, and USB drives in the same browser as your local files. Strata mounts them through GIO/GVfs on demand.
Open an SMB share
On Arch or Omarchy, install the SMB backend first:
sudo pacman -S --needed gvfs-smb
Press Ctrl+L, type smb://server/share, and press Enter. Strata mounts the
share and opens it.
If the server wants credentials, Authentication required shows only the fields it asks for, such as Username, Domain, and Password. For a guest share, choose Anonymous under Connect as when offered. Password storage defaults to Don't remember; Until logout or Forever hands the password to your desktop keyring. Click Connect.
To browse instead, click Network in the sidebar, then a host, then a share. A mounted share appears under DEVICES; right-click it and choose Disconnect when done.
Connect over SFTP
Press Ctrl+L and enter one of these:
sftp://host/path
sftp://user@host/path
sftp://user@host:2222/path
These connect as your local user on port 22, as user, and as user on port
2222.
With your key in an SSH agent, or an unencrypted key, the folder opens with no prompt. Load an encrypted key into the agent first:
ssh-add ~/.ssh/id_ed25519
Otherwise Strata asks for a password, or shows Passphrase required when GVfs requests your key's passphrase.
Trust a host key
On a first connection, or when a server's key changes, Strata shows Verify server identity. It repeats the backend's question and offers the backend's own buttons. Strata never answers for you.
Verify the fingerprint with the server's administrator, outside Strata, before you continue. A changed key can mean interception. Decline with the rejecting button or Escape, and Strata returns to the previous folder.
Connect a phone or camera
Phone backends are optional. On Arch or Omarchy, install what you need:
# iPhone or iPad app documents (AFC):
sudo pacman -S --needed gvfs-afc usbmuxd
# Camera/PTP photo access, including compatible iPhones:
sudo pacman -S --needed gvfs-gphoto2
# Android (MTP):
sudo pacman -S --needed gvfs-mtp
Quit every Strata window and reopen it. Unlock the phone and connect a USB data cable. On an iPhone, accept Trust This Computer; on Android, choose file transfer in the phone's USB preferences. Click the phone under DEVICES.
A camera entry opens one flat Photos view of every JPEG, HEIC, MOV, MP4, and recognized RAW file. Android and iPhone app-document entries browse as normal folders.
Good to know:
- Photos lists files in discovery order. Choose Name or Modified in the sort menu to reorder.
- Copy, preview, and delete act on the originals on the phone.
- Thumbnails are the camera's own previews; without one, the file keeps its icon.
- Some iPhones show an empty photo store until your distribution ships a fixed libgphoto2.
Mount, unlock, and eject drives
Plugged-in drives appear under DEVICES. Click an unmounted one to mount and open it.
An encrypted drive shows a lock button. Click the row or the button, then enter the passphrase in Passphrase required. To lock it, click the open-lock button, or right-click and choose Lock. If its passphrase is saved, Strata asks Forget saved password?; Forget and lock removes it and locks.
To remove a drive, click its eject button, or right-click and choose Eject (Unmount on drives that cannot eject). Strata flushes pending writes first; the row shows a spinner until the release finishes. Unplug once the spinner stops with no error. A slow release opens a progress window; Hide dismisses it without stopping the release. If it is open when an eject finishes, it shows Safe to remove.
Full detail: SFTP locations, Installation and desktop integration
10xer mode
Press Ctrl+Shift+M for a Yazi-style keymap: letters become commands and j
and k move. Press it again to go back.
What 10xer mode changes
- Letters are commands. Typing
dasks to trash the item; it no longer starts a filter. - Less chrome. The window's Search button, each pane's close, filter, refresh, and sort controls, and the List and Icons pane header hide.
- The footer is the command line. Prompts such as
filter:andgo ›open there, and a chord such asglists its next keys above it. - F1 lists only 10xer keys. Press F1 or
~to see what runs now. - Some default keys change. Space selects instead of previewing, Ctrl+R inverts the selection, Ctrl+B and Ctrl+F page up and down, and Ctrl+N shows or hides the sidebar.
Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+Z, Ctrl+K, and Ctrl+L work as in the default map.
Turn it on and off
- Press Ctrl+Shift+M, or press Ctrl+, and turn on 10xer mode under BROWSING in General.
- Check for the 10X pill at the far right of the footer.
- Press Ctrl+Shift+M again, or turn the switch off in Settings, to leave.
Ctrl+Shift+M is the only key that leaves:
qand Escape never do.
The choice is saved for every window and the next launch. Strata's system file chooser follows it too.
Leaving the mode closes prompts and clears f filters, s searches, and find
highlights. Your selection stays.
Keys to learn first
You don't need to memorize every key. Five keys start a chord: press one, and a panel above the footer lists the keys that can follow. Remember what each chord is for and read the rest off the panel. Escape cancels a chord.
| Press | Think | For example |
|---|---|---|
g | "go somewhere" | g h Home, g d Downloads, g g first item, g Space to type a path |
; | "do something" | ; t terminal here, ; c compress, ; 1 first custom action |
t | "tabs" | t n new tab, t x close it, t 1 first tab |
c | "copy a path or name" | c c path, c n name |
, | "sort by something" | , a name, , m modified; Shift reverses |
The rest are single keys. They work in List and Columns. In Icons, h, j,
k, and l move between tiles; press Enter to open one. Capitals mean Shift:
G is Shift+G.
| Keys | What it does |
|---|---|
j / k | Next / previous item |
h / l | Parent folder / open the folder |
Enter or o | Open the item, including files |
G | Last item |
H / L | Back / forward in history |
i | Preview a file while you keep moving |
| Space | Select or unselect, then move down |
v | Select a range as you move |
y / x / p | Copy / cut / paste |
d | Move to Trash; d again confirms |
a | Create a file; end with / for a folder |
r | Rename |
/, a name, Enter; then n / N | Find a name, then next / previous match |
f | Filter this folder |
s | Search this folder and its subfolders |
z | Jump to a visited folder |
| Escape | End one thing: prompt, filter, range, preview, then selection |
Q | Close the window |
Try it: press s, type readme, and press Enter. The cursor lands on the
first hit; Enter again opens it.
y, x, and d act on the selection, or on the focused item when nothing is
selected. Press l on a file to move the keys into its preview, and h to
hand them back.
Type a few letters, fzf-style
Prompts that pick a file or folder match the way fzf does. Type a few letters of each word, separated by spaces, in any order. Case never matters.
| Type | Matches |
|---|---|
dev str | Each term's letters in order, terms in any order: ~/dev/strata |
'read | read as one unbroken run |
^read | A name or path that starts with read |
.md$ | A name or path that ends in .md |
!test | Leaves out anything containing test |
These prompts use it:
| Prompt | Matches against |
|---|---|
f filter | Names of the folder's own items |
s search | Paths below the current folder |
z jump, Z recent | Folders you have opened |
g Space, M, C, ; E | Folders below the current one, to go to, move or copy to, or extract to |
/ find is the exception: it matches plain text in the name.
Who it is for
Turn it on if you use Yazi, Ranger, or Vim, or want your hands on the keyboard and fewer buttons on screen.
Leave it off if you browse with the mouse or find files by typing their name. In 10xer mode, Type to search, Keep arrows in file list, and Include subfolders read Not used in 10xer mode.
While the mode is on, its Settings row reads (experimental feature, under active development): expect keys to change between releases.
Full detail: the 10xer mode reference lists every key, chord, prompt, and file chooser rule.
Installation and desktop integration
Installation
Arch Linux and Omarchy are the primary supported environments. Current binaries require glibc 2.39 or newer and the runtime libraries listed below. Strata targets 64-bit Linux on Wayland. GTK may use another display backend the host provides, but Wayland is the primary display stack.
Interactive installation
The interactive installer detects the Linux architecture, glibc version, Arch Linux, and Omarchy 3 or 4. It installs the latest verified stable release and offers optional desktop-menu, default-folder-handler, "Open file location", system file chooser, encrypted-volume unlock, SMB, broader image/RAW, and Omarchy keybind integration:
curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh | bash
The installer shows every privileged package operation before asking to run it.
It always checks the archive against its published .sha256 file before
extracting anything. When GitHub CLI is installed and logged in, it also runs
gh attestation verify, and a failed check stops the install. Without gh, or
with gh logged out, it warns ("continuing after HTTPS download and checksum
verification") and continues. The binary is installed per-user at
~/.local/bin/strata.
For an unattended Arch or Omarchy installation, pass --non-interactive. This
installs required dependencies and the binary without prompting; optional
integrations remain disabled unless explicitly selected. For example, on Omarchy:
curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh \
| bash -s -- --non-interactive \
--with-smb \
--with-raw \
--with-desktop-entry \
--with-folder-association \
--with-omarchy-keybinds \
--with-udiskie-unlock
--with-omarchy-keybinds requires Omarchy 3 or 4, and --with-udiskie-unlock
requires udiskie on PATH. On generic Arch, leave out the flags that do not
apply. Otherwise the installer exits with an error after it has installed the
binary and any integration it set up before that flag's step.
Each --with-* flag and --without-file-chooser implies --non-interactive,
and integrations you do not name are declined. An unknown option exits with
"Unknown option: <option> (run with --help for usage)." Folder association implies
the desktop entry and --with-file-manager. Use --with-file-manager by itself
to enable only "Open file location" integration. File chooser replacement is
separate: use --with-file-chooser to opt in, or --without-file-chooser to keep
your current chooser. You can set it up later in Settings → General → DESKTOP
INTEGRATION → System file manager (see Set up from Settings). Neither folder
association nor an unattended install enables the chooser automatically.
Encrypted-volume unlock is offered on Omarchy 3 or 4 (the installer asks; default
No), and on generic Arch only when udiskie is already on PATH. The installer
never installs the udiskie package. Unattended installs need
--with-udiskie-unlock; --non-interactive alone and other --with-* flags
leave it declined. Restore on Arch with strata --uninstall-udiskie-unlock, not
Settings.
Non-interactive package installation requires passwordless sudo or cached credentials. Run ./install.sh --help for the full option list.
Phone backends are not installed by the script. For optional iPhone/iPad or Android access, follow Connecting phones after installation.
System checks and dependencies
Run the installer as your normal desktop user. Run as root, it exits with "Run
this installer as your normal desktop user, not as root." An interactive run
needs a terminal; without one it exits with "This interactive installer needs a
terminal." Under curl … | bash, every prompt, including pacman's, reads from
the terminal. On a system other than Linux it exits with "The prebuilt Strata
release supports Linux only." On a machine other than x86_64 or aarch64 it exits
with "Strata has no prebuilt release for <machine>." On a Linux system without
glibc it exits with "Strata requires a glibc-based Linux system." With glibc
older than 2.39 it exits with "Strata requires glibc 2.39 or newer (found
<version>)."
It then prints the detected Linux distribution, the architecture (as the release
target), the glibc version, and "Omarchy: major version N" or "Omarchy: not
detected". The Omarchy major version is the first 3.N or 4.N in the output of
omarchy version, then in /usr/share/omarchy/version, then in
~/.local/share/omarchy/version. Output such as dev (b280f130) or Omarchy 2.3.1 counts as not detected.
On Arch, an Arch derivative, or Omarchy, it lists missing required packages and
asks "Install these packages with sudo pacman?" (default Yes). It then asks
separately about SMB support (gvfs-smb) and broader image and camera RAW support
(imagemagick, libraw, dcraw), each defaulting to No. On other distributions
it lists the required libraries, including the GVfs UDisks2 volume monitor, and
exits unless you confirm they are installed. --non-interactive exits there with
"Non-interactive dependency installation currently supports Arch-based systems
only."
Install and integration prompts
The installer always installs the latest stable release. If GitHub's latest
release tag is not shaped vX.Y.Z, it exits with "GitHub returned an unexpected
stable release tag: <tag>". An archive missing the
strata binary, the desktop entry, or the icon is rejected before installation.
If ~/.local/bin/strata already exists, it asks "Replace the existing …?"
(default No). An unattended run exits instead: "… already exists; remove it or
run the interactive installer to replace it."
"Add Strata to your desktop application menu?" defaults to Yes. The installer
writes the entry, the icon, and the "Open file location" service under
${XDG_DATA_HOME:-~/.local/share}, in applications/,
icons/hicolor/scalable/apps/, and dbus-1/services/, with Exec= set to
~/.local/bin/strata. Only after a Yes
does it ask "Make Strata the default application for opening folders?", which
defaults to No. Accepting it also installs the "Open file location" service
without asking. If xdg-mime still reports another folder handler afterwards,
the installer exits with an error. When you decline the menu entry or folder
association, it asks separately 'Use Strata for "Open file location" from other
applications?' (default No).
The questions about the system file chooser, Omarchy keybinds, and encrypted-volume unlock each default to No. The Omarchy keybind question is asked even when Omarchy is not detected; answering Yes there exits with "--with-omarchy-keybinds requires Omarchy 3 or 4."
The file chooser question reads "Replace your current Open/Save chooser with
Strata in portal-aware apps? (Restarts the portal service; close open file
dialogs first.)" Accepting it, or passing --with-file-chooser, restarts the
portal service. On Arch, an Arch derivative, or Omarchy, it first installs
xdg-desktop-portal if that package is missing.
The installer finishes by printing the installed version, the archive's source
commit, and the binary path. It warns when ~/.local/bin is not on PATH.
AI-assisted installation
Use this option to have a coding agent install and verify the latest release archive.
Give this prompt to a coding agent with terminal access:
Install the latest stable Strata release from https://github.com/lgse/strata safely.
Before changing anything:
1. Confirm this is a glibc-based Linux system with a graphical GTK4 environment.
2. Detect whether the machine is x86_64 or aarch64 and select only the matching
*-unknown-linux-gnu archive from the canonical lgse/strata GitHub release.
3. Show me the runtime packages you need and ask before using sudo or changing
my default file-manager association.
Then:
- Install the required GTK4, GtkSourceView 5, Poppler GLib, Fontconfig, Bubblewrap,
FFmpeg/GStreamer, and desktop-integration runtime dependencies using the system
package manager. Add gvfs-smb only if I want SMB support.
- Ask whether I want phone access. On Arch/Omarchy, add gvfs-afc and usbmuxd for
iPhone/iPad app documents, gvfs-gphoto2 for camera/PTP photo access, or gvfs-mtp
for Android file transfers, only if requested. Other distributions need their
equivalent GVfs backends.
- Download the archive and its matching .sha256 file from the latest GitHub release.
- Verify the checksum with sha256sum --check. If GitHub CLI is installed and
authenticated, also verify GitHub Actions provenance with
`gh attestation verify <archive> --repo lgse/strata`. Stop if either attempted
verification fails; never install a binary with an invalid checksum.
- Extract it and install `strata` to ~/.local/bin/strata without overwriting an
unrelated file. Ensure ~/.local/bin is on PATH.
- Ask whether I want a per-user desktop entry and inode/directory association;
if yes, install the archive's io.github.lgse.Strata.desktop and io.github.lgse.Strata.svg
under ~/.local/share, pointing Exec at the installed binary, then refresh the
desktop database and icon cache.
- Separately ask whether Strata should handle "Open file location" requests. If
yes, verify no other per-user service provides org.freedesktop.FileManager1,
then install the archive's io.github.lgse.Strata.FileManager1.service under
~/.local/share/dbus-1/services with Exec pointing at the installed binary.
- Ask before editing udiskie config to use Strata for encrypted-volume unlock.
Do not install the udiskie package. Do not send Arch users to Settings for
this row; restore on Arch with `strata --uninstall-udiskie-unlock`.
- Launch `strata`, report its installed version/source release, and verify the
desktop association if one was requested. Do not weaken the preview sandbox.
Manual installation
Install the release archive directly if you prefer to perform each step yourself.
1. Check the architecture and install dependencies
case "$(uname -m)" in
x86_64) target=x86_64-unknown-linux-gnu ;;
aarch64) target=aarch64-unknown-linux-gnu ;;
*) echo "Strata has no prebuilt release for $(uname -m)" >&2; exit 1 ;;
esac
printf 'Use the %s release archive.\n' "$target"
getconf GNU_LIBC_VERSION # must report glibc 2.39 or newer
On Arch Linux or Omarchy:
sudo pacman -S --needed bubblewrap desktop-file-utils ffmpeg ffmpegthumbnailer fontconfig \
gstreamer gst-libav gst-plugins-base gst-plugins-good gtk4 gtksourceview5 gvfs poppler-glib \
xdg-utils
# Optional SMB and broader camera RAW support, plus squashfs-tools:
sudo pacman -S --needed gvfs-smb imagemagick libraw dcraw squashfs-tools
GTK 4.12 or newer and glibc 2.39 or newer are required. Other glibc-based distributions may work when they provide equivalent runtime libraries, but their package names and binary compatibility vary. Systems with an older glibc must build Strata from source.
Device discovery requires the GVfs UDisks2 volume monitor (gvfs on Arch and
Fedora; gvfs-daemons on Debian/Ubuntu). Without that backend, removable drives
may be absent from DEVICES. SMB support remains optional. Phones need additional
backends; see Connecting phones.
2. Download and verify
From the latest release, download the .tar.gz matching $target and its identically named .sha256 file over HTTPS. Then verify its digest:
cd ~/Downloads
archive="strata-<version>-${target}.tar.gz"
sha256sum --check "${archive}.sha256"
If GitHub CLI is installed and authenticated, you can additionally verify the archive's signed GitHub Actions provenance before extracting it:
gh attestation verify "$archive" --repo lgse/strata
Every verification you run must succeed. Extract the archive, install the binary, and confirm it starts:
tar -xzf "$archive"
install -Dm755 "${archive%.tar.gz}/strata" "$HOME/.local/bin/strata"
command -v strata
strata
If command -v fails, add $HOME/.local/bin to your shell's PATH. Every archive contains SOURCE_COMMIT, identifying the exact source revision used by GitHub Actions.
Debug a release crash
Download the matching strata-<version>-<target>.debug asset from the same release and place it beside the installed strata binary, keeping its filename unchanged. Then run coredumpctl debug strata; GDB will load its Rust function names and source lines.
3. Update or uninstall
In-app updates verify signed release manifests inside Strata, without gh, a GitHub account, or a token. Releases published before signed manifests were introduced require manual installation; the updater never falls back to checksum-only verification.
For a manual installation, use Settings → Updates for verified in-app updates, or repeat the download, verification, and install steps for a newer release. When ${XDG_DATA_HOME:-~/.local/share}/applications/io.github.lgse.Strata.desktop exists, an in-app update rewrites it and ${XDG_DATA_HOME:-~/.local/share}/icons/hicolor/scalable/apps/io.github.lgse.Strata.svg from the new archive. Without that entry it writes neither file. The rewritten Exec= line points at the installed binary's path, quoted when the path has spaces or shell characters, with % doubled and the %U field code kept. This holds even when the running binary was already replaced on disk. If the user opted into Strata's system file chooser, the update restarts the portal frontend so subsequent dialogs use the newly installed build. Package-managed installations are updated only by their system package manager (see Package-managed installations). To remove a per-user installation, first run strata --uninstall-portal if you opted into the system file chooser, and strata --uninstall-udiskie-unlock if you opted into encrypted-volume unlock. Then:
data="${XDG_DATA_HOME:-$HOME/.local/share}"
rm -f ~/.local/bin/strata \
"$data"/applications/io.github.lgse.Strata.desktop \
"$data"/dbus-1/services/io.github.lgse.Strata.FileManager1.service \
"$data"/icons/hicolor/scalable/apps/io.github.lgse.Strata.svg
update-desktop-database "$data"/applications 2>/dev/null || true
gtk-update-icon-cache -qtf "$data"/icons/hicolor 2>/dev/null || true
User preferences and custom themes remain under the XDG configuration directories so an uninstall does not destroy personal settings.
Arch packages
The Arch packages strata-bin (latest stable release) and strata-rc-bin
(newest stable, alpha, beta, or release-candidate release) are prepared but not
yet published on the AUR. Each repackages the release archive for x86_64 or
aarch64, each architecture with its own pinned SHA-256, and installs the
archive's strata binary byte for byte as /usr/bin/strata, without stripping
it again. Debug symbols are in the release's separate .debug asset (see Debug
a release crash). Each package provides
strata=<pkgver>, conflicts with strata and with the other package, and is
licensed MIT and LicenseRef-UnRAR. A prerelease version drops only its
hyphen: 0.10.0-rc.1 is packaged as 0.10.0rc.1. Nightly builds have no
package; install them from the release archive and update in the app. A
package's channel is fixed, so to change channel, install the other package.
- The desktop entry goes to
/usr/share/applicationsand the icon to/usr/share/icons/hicolor/scalable/apps. An archive without them still packages, with a warning and no launcher. - The "Open file location" service goes only to
/usr/share/strataas an inactive template; see "Open file location" from other applications. LICENSEandTHIRD_PARTY_LICENSES.md, plusUnRAR.txtwhen the archive has it, go under/usr/share/licenses/<pkgname>/.- Required:
bubblewrap,fontconfig,glibc>=2.39,gstreamer>=1.20,gst-plugins-base,gtk4>=4.12,gtksourceview5,gvfs, andpoppler-glib. - Optional:
ffmpeg,ffmpegthumbnailer,gst-libav,gst-plugins-good,gvfs-smb,imagemagick,libraw,squashfs-tools(listed for AppImage icons, which Strata does not show), andxdg-terminal-exec(Open in Terminal).
In-app updates
Install update on the Settings → Updates row, or Download update in the update dialog, starts the install at once. Only one install runs at a time; starting another shows "Another install is already running — try again shortly."
- The row reads "Verifying update…" while the signed manifest is fetched, then "Downloading update… N%", "Verifying update…", "Installing update…", and "Finalizing update…". Its button reads Cancel.
- Cancel during a download stops it within about a second, shows "Update cancelled", and leaves the installed binary unchanged. In the dialog, Cancel, the close button, Escape, and a click outside it do the same and close the dialog.
- Once finalizing begins, the row's Cancel is disabled and the dialog cannot be dismissed until the install ends.
- A failure shows "Couldn't install update: <reason>". The row's button becomes Check now, and the dialog's becomes Close.
- A download fails after 30 seconds to connect ("Could not reach the download server — check your connection and try again"), or after 30 seconds without receiving any bytes, the wait for the server's first reply included ("The download stalled — check your connection and try again"). Sending the request and receiving the response headers must each finish within 60 seconds. There is no total time limit; see Signed updates.
- On success the status reads "Update installed — restart to apply". Strata
sends SIGTERM to your other Strata processes started without a flag, or with
--portal, that still run the old binary from the same install path, and SIGKILL to any still running 5 seconds later. Only your own user's processes are affected. Processes started with other flags keep running: preview helpers, an--unlock-volumewindow, and astrata --gapplication-serviceinstance started by "Open file location". Strata binaries installed at other paths also keep running. Strata then closes its windows and relaunches the new binary. A running file operation that guards closing blocks the restart and shows its close warning. - The previous binary is kept beside the new one as
.strata-update-rollback. It is restored if the new binary fails its startup probe or exits with an error within 20 seconds, and deleted 60 seconds after a successful start.
See Signed updates for manifest and archive checks.
Package-managed installations
Strata treats itself as package-managed when its install prefix has
share/strata/install-source.toml, which the Arch packages write, or when pacman
owns the binary. The marker counts even when it cannot be read or parsed. A
pacman-owned binary on a system whose /etc/os-release has ID=omarchy is
Omarchy-managed. If pacman is installed but the ownership query cannot run,
Strata also disables in-place updates. The Omarchy and pacman classification
applies only without the marker. With the marker, Strata follows the marker's
AUR package, even on Omarchy or when pacman owns the binary. A binary no package owns, such as
~/.local/bin/strata, keeps in-place updates.
- A package-managed install never downloads an update in the app. Its status line adds "Managed by Omarchy", "Managed by pacman", or "Managed by" the package's manager.
- With the marker file, a Package-managed installation row names the manager,
package, tracked channel, update instruction, and alternate package. The
Release channel menu is disabled and follows the package's channel;
rcandpreviewshow as Preview. - An Omarchy or pacman install without the marker hides the Release channel row.
- Update checks ask the AUR for the marker's package, the Omarchy repository for an Omarchy install, or the pacman sync databases otherwise. A notice appears only when that version is newer and its GitHub release exists. A stable package version must match a GitHub release not marked prerelease; a prerelease version may match either kind.
- With an update available, Omarchy offers Open Omarchy Update, which runs
omarchy updatein your terminal. An AUR install offers Open AUR Update, which runs<helper> -Syu <package>withyay,paru,pikaur, ortrizenwhen one is onPATH, or View on AUR without one. A pacman install tells you to install it through a full system update.
Usage and desktop integration
Launch Strata with optional paths or URIs:
strata # reopen the last session's tabs, or the default directory
strata ~/Documents # a specific directory
strata ~/notes.txt # its folder, with the file selected
strata sftp://host/dir # a remote location
strata --unlock-volume DEVICE # unlock an encrypted volume
strata --install-udiskie-unlock # install Strata as the udiskie unlock handler
strata --uninstall-udiskie-unlock # restore the previous udiskie configuration
strata --version # print the installed version
With no arguments, Strata reopens the tabs saved from the last session while Settings → General → STARTUP → Restore open tabs is on, which is the default. Without a saved session, or with that switch off, it opens the default directory.
Each argument opens its own window, whether or not Strata is already running. A
file argument, or a file:// URI, opens its parent folder with that file
selected. A symlink to a folder opens the folder, and a broken symlink is
selected in its parent. trash:///, smb://, and sftp:// arguments open that
location; a remote file URI opens its parent with the file selected. An unmounted
remote is mounted first, with the desktop's sign-in prompt when needed. Paths
whose names are not valid UTF-8 open normally, and a file argument selects only
that file even when another name displays the same.
The window appears at once and stays responsive while Strata checks the argument. If the check takes over 1 second, the pane shows a spinner, "Connecting to location…", and Cancel, which opens the home folder. A missing or unreadable argument shows "The requested location is unavailable" with its path and a Retry button, never a password from the URI. Retry checks again, so a folder created after the failure opens. If you navigate elsewhere or close the window while Strata is still checking, the check is dropped and nothing navigates or reports an error later. Strata also opens normally when launched with its output going to a closed pipe.
strata --version prints one line, such as strata 1.0.0, and exits without
opening a window. Prerelease builds include their suffix, such as -rc.1,
matching Settings → Updates. The flag must come first: strata ~/Documents --version launches Strata instead.
In the default map, useful shortcuts include Ctrl+K to search Home and mounted local drives from any folder, Ctrl+L for a path or URI, Ctrl+F to filter the current pane, Ctrl+Z to undo or Ctrl+Shift+Z to redo the latest reversible file operation, Space for preview, F2 to rename, Alt+Left and Alt+Right for Back and Forward, and Alt+Up for the parent folder.
Toggle 10xer mode with Ctrl+Shift+M for Yazi-style navigation and footer prompts; press Ctrl+Shift+M again to return to the default map. In 10xer mode, q in the file list does nothing, and Q closes the current window. In List and Columns, l / Right on a previewable file moves the keys into its preview, h returns them to the listing without closing the preview, and i toggles the preview.
In narrow or highly scaled windows, the file view takes priority: the preview shrinks, then hides when there is not enough room for both. Widening the window restores the preview and its session width automatically. Hidden previews pause playback and defer loading new selections; unchanged previews return without reloading the file.
Desktop entry
Every release archive ships io.github.lgse.Strata.desktop and the Strata application icon io.github.lgse.Strata.svg. Install both to give Strata a per-user launcher with its own icon in launchers, docks, task switchers, and window overviews, and optionally make Strata the default directory handler:
cd ~/Downloads/"${archive%.tar.gz}"
install -Dm644 io.github.lgse.Strata.svg \
~/.local/share/icons/hicolor/scalable/apps/io.github.lgse.Strata.svg
install -d ~/.local/share/applications
sed "s|^Exec=strata |Exec=$HOME/.local/bin/strata |" io.github.lgse.Strata.desktop \
> ~/.local/share/applications/io.github.lgse.Strata.desktop
update-desktop-database ~/.local/share/applications
gtk-update-icon-cache -qtf ~/.local/share/icons/hicolor 2>/dev/null || true
xdg-mime default io.github.lgse.Strata.desktop inode/directory
xdg-mime query default inode/directory
The final command should print io.github.lgse.Strata.desktop. The desktop entry's filename matches the io.github.lgse.Strata application ID that Strata's windows report, so desktop shells match a running window to this entry and draw its Icon value. The entry sets Icon=io.github.lgse.Strata and StartupWMClass=io.github.lgse.Strata. Log out and back in if a shell caches launcher icons.
The entry declares MimeType=inode/directory; and
Categories=Utility;FileTools;FileManager;, so launchers list it as a file
manager and it can be the default folder handler. Its generic name, comment, and
keywords are translated into French, German, Spanish, Japanese, Brazilian
Portuguese, Korean, Vietnamese, Italian, Russian, and Simplified Chinese. It
ships with Exec=strata %U; the commands above, the installer, and mise run install-local rewrite that to the installed binary's absolute path. Strata also
bundles its icon and sets it as the GTK default window icon.
When building from source, mise run install-local installs the binary, icon, and desktop entry in the same locations, and mise run uninstall-local removes them.
"Open file location" from other applications
Browsers and GTK/GNOME applications reveal a file by calling the org.freedesktop.FileManager1 D-Bus interface instead of consulting the inode/directory association. The interactive installer offers this separately; for unattended installation, pass --with-file-manager. Folder association enables it automatically.
For a source installation, enable Strata as the per-user activatable provider explicitly:
mise run install-file-manager
For an AUR package, copy its inactive service template into your per-user service directory:
install -Dm644 /usr/share/strata/io.github.lgse.Strata.FileManager1.service \
~/.local/share/dbus-1/services/io.github.lgse.Strata.FileManager1.service
For a release archive installation, install the included service manually instead:
cd ~/Downloads/"${archive%.tar.gz}"
install -d ~/.local/share/dbus-1/services
sed "s|^Exec=/usr/bin/strata |Exec=$HOME/.local/bin/strata |" \
io.github.lgse.Strata.FileManager1.service \
> ~/.local/share/dbus-1/services/io.github.lgse.Strata.FileManager1.service
A per-user provider takes precedence over system providers shipped by other file managers. Before enabling Strata manually, remove any other per-user service whose Name is org.freedesktop.FileManager1; two providers for the same name in one service directory are chosen arbitrarily. The installer and mise run install-file-manager refuse to install while another per-user service in that directory provides org.freedesktop.FileManager1. If another file manager already owns the bus name, exit it before testing. Use mise run uninstall-file-manager for a source installation, or remove the per-user service file, to disable Strata again.
While Strata is running, it claims org.freedesktop.FileManager1 on the session bus unless another program already owns that name. The service file lets a call start Strata (strata --gapplication-service) when it is not running. If another file manager already owns the bus name, calls keep reaching that file manager. Strata then answers ShowFolders, ShowItems, and ShowItemProperties, and each call opens a new Strata window:
ShowFoldersopens each named folder with nothing selected.ShowItemsopens the folder that holds each named item, with the item selected and focused. Items that share a folder open in one window; each other folder opens its own window, in the order listed.ShowItemsonfile:///opens/with nothing selected.ShowItemPropertiesdoes the same asShowItemsand also opens Properties for the first item listed.- Revealing a dotfile while hidden files are off turns hidden files on and selects it.
- When two files' names are not valid UTF-8 and display the same,
ShowItemsselects only the file the URI names. - A remote URI such as
sftp://host/dir/fileis mounted first, then revealed. If the mount fails or is cancelled, nothing is revealed. - Each method takes a list of URIs and a startup ID (
as,s). Strata ignores the startup ID, and a call with other arguments fails withorg.freedesktop.DBus.Error.InvalidArgs.
For example:
busctl --user call org.freedesktop.FileManager1 /org/freedesktop/FileManager1 \
org.freedesktop.FileManager1 ShowItems ass 1 "file://$HOME/Downloads" ""
Set up from Settings
Settings → General → DESKTOP INTEGRATION → System file manager lists Open and Save dialogs, Opening folders, and Reveal in File Manager, each marked configured or not. On Omarchy it also lists Keyboard shortcuts. Close open file dialogs before changing setup.
- Complete setup installs the system file chooser, makes
io.github.lgse.Strata.desktoptheinode/directoryhandler, and installs the per-user "Open file location" service. On Omarchy 3 or 4 it also binds Super+Shift+F and Super+Alt+Shift+F to Strata in~/.config/hypr/bindings.conf, orbindings.luaon Omarchy 4. - If
hyprctl configerrorsreports errors after that edit, Complete setup restores the previous bindings file and keeps astrata-keybind-backup-copy. - A bindings file that is a symlink you own is written through, and the link is kept. A dangling link, or a link or target owned by another user, makes setup fail without writing. Existing permission bits are kept.
- With a symlinked bindings file, the
strata-keybind-backup-copy is written in the link's directory. With a dangling link, Complete setup fails naming the missing target, and Restore default leaves the shortcuts and the link unchanged. - Complete setup fails with "Another per-user FileManager1 provider is already installed: <path>" when another service owns that name. The button is hidden once every line is configured.
- Restore default appears while any part is installed. It removes the
service and the chooser, and returns
inode/directoryto the handler recorded before setup, or Nautilus. It leaves the folder handler alone when it no longer points to Strata. With no recorded handler and no Nautilus, it fails with "No previous folder handler was recorded and Nautilus was not detected. Choose another default file manager first, then retry Restore default." - On Omarchy, Restore default replaces Strata's shortcut block with
nautilus --new-windowbindings. Without Nautilus, it reports "Nautilus was not detected; the Strata keyboard shortcuts were left unchanged." It refuses to change a Strata shortcut block you edited by hand.
Make Strata the Omarchy file manager
The XDG association above handles folders opened by applications. On current Lua-based Omarchy releases, also override the stock Nautilus shortcuts in ~/.config/hypr/bindings.lua so Omarchy launches Strata directly.
The installer's "Replace Omarchy's Nautilus file-manager keybinds with Strata?"
(default No), or --with-omarchy-keybinds, does this for you. It appends a
marked block that rebinds Super+Shift+F and Super+Alt+Shift+F to Strata, in
~/.config/hypr/bindings.conf on Omarchy 3 or ~/.config/hypr/bindings.lua on
Omarchy 4. It first backs up an existing file as <file>.bak.<timestamp>. If
hyprctl configerrors reports errors after the reload, it restores the previous
file and exits with Hyprland's errors. If the block is already present, it
changes nothing. Without a running Hyprland, it writes the block and warns that
the file could not be reloaded.
To make the change by hand on Omarchy 3, append this to
~/.config/hypr/bindings.conf:
unbind = SUPER SHIFT, F
unbind = SUPER ALT SHIFT, F
bindd = SUPER SHIFT, F, File manager, exec, uwsm-app -- strata
bindd = SUPER ALT SHIFT, F, File manager (cwd), exec, uwsm-app -- strata "$(omarchy-cmd-terminal-cwd)"
On Omarchy 4, follow the steps below.
First inspect the active bindings and back up your user configuration:
omarchy menu keybindings --print | grep -i "file manager"
cp ~/.config/hypr/bindings.lua ~/.config/hypr/bindings.lua.bak.$(date +%s)
Append these overrides to ~/.config/hypr/bindings.lua:
-- Use Strata instead of Nautilus for Omarchy's file-manager shortcuts.
hl.unbind("SUPER + SHIFT + F")
hl.unbind("SUPER + ALT + SHIFT + F")
o.bind("SUPER + SHIFT + F", "File manager", { launch = "strata" })
o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)",
"uwsm-app -- strata \"$(omarchy-cmd-terminal-cwd)\"")
The stock shortcut is Super+Shift+F, not Ctrl+Shift+F. To support the Ctrl chord too, first confirm that it is not assigned to another action, then optionally append:
o.bind("CTRL + SHIFT + F", "File manager", { launch = "strata" })
Apply and validate the configuration:
hyprctl reload
hyprctl configerrors
omarchy menu keybindings --print | grep -i "file manager"
hyprctl configerrors should produce no errors. These user overrides survive Omarchy updates; do not edit files under /usr/share/omarchy/.
Unlock encrypted volumes on Omarchy
On Omarchy 3 or 4, the installer asks whether to use Strata for encrypted-volume unlock (default No). Settings → General → DESKTOP INTEGRATION includes Unlock encrypted volumes. Choose Use Strata so plugging in an encrypted drive opens Strata's password prompt instead of udiskie's dialog. Restore default returns udiskie to its previous configuration. Restoring also deletes the restore state in ~/.local/share/strata/udiskie-install/.
On generic Arch, the installer offers the same step only when udiskie is already on PATH. Restore there with strata --uninstall-udiskie-unlock; Settings for this row stays Omarchy-only.
The same setup is available unattended:
strata --install-udiskie-unlock
strata --uninstall-udiskie-unlock
This edits ~/.config/udiskie/config.yml and records restore state in ~/.local/share/strata/udiskie-install/state.toml. It is not a saved Strata preference. The Settings row appears only when Omarchy is detected and udiskie is on your PATH; the CLI flags are unattended and are not Omarchy-gated. Unattended installer opt-in is --with-udiskie-unlock.
Setup rewrites config.yml with a managed header, sets udiskie's event_hook to
a list of the installed binary's absolute path followed by --udiskie-hook {event} {id_usage} {device_file} {id_uuid}, sets
password_prompt: false, and turns off LUKS automount. When only config.json
exists, setup converts it to config.yml, and restore writes it back as JSON.
Setup then restarts udiskie, or starts udiskie --automount --no-notify --no-tray if none is running; restore restarts udiskie only if it is running.
If udiskie cannot be restarted, the command reports "Saved the udiskie
configuration. Restart udiskie or log out for it to take effect." A config.yml
that is a symlink or other non-regular file is refused with "Refusing to replace
non-regular udiskie configuration <path>". Setup also refuses a configuration
that is not a YAML mapping, whose program_options is not a mapping, whose
device_config is not a list, or whose existing event_hook or
password_prompt is not a boolean, string, or list of strings. It reports
"Refusing to change udiskie configuration: …" and leaves the file unchanged.
Neither command installs or removes the
udiskie package. Use Strata shows only while the integration is not
configured, and Restore default only while there is something to restore.
On Omarchy without udiskie on PATH, the installer warns and skips this step;
with --with-udiskie-unlock it exits with "udiskie is not on PATH;
--with-udiskie-unlock requires udiskie." On any other system that does not
qualify, --with-udiskie-unlock exits with "--with-udiskie-unlock requires
Omarchy 3 or 4, or an Arch-based system with udiskie on PATH."
For an added encrypted volume, the hook runs strata --unlock-volume DEVICE, or
passes the volume's UUID when udiskie reports no device file. It ignores every
other event. --unlock-volume takes a device path or LUKS UUID and
opens Strata's password prompt for that volume. If the volume has not appeared
after 1 second, the window shows "Waiting for encrypted volume…" with Cancel.
After 8 seconds without a match it shows "The encrypted volume was not found",
and an unencrypted volume shows "This is not an encrypted volume". Any other
operand fails with "invalid --unlock-volume operand", and combining it with file
arguments fails with "cannot combine --unlock-volume with file arguments".
Connecting phones
Strata discovers and mounts phones through GIO/GVfs. The required phone backends
are optional and are not installed by install.sh. On Arch Linux or Omarchy,
install only the support you need:
# iPhone or iPad app documents (AFC):
sudo pacman -S --needed gvfs-afc usbmuxd
# Camera/PTP photo access, including compatible iPhones:
sudo pacman -S --needed gvfs-gphoto2
# Android (MTP):
sudo pacman -S --needed gvfs-mtp
Other distributions need equivalent GVfs AFC, gphoto2/PTP, or MTP backends; package names vary.
- iPhone/iPad: unlock the device, connect it with a USB data cable, and accept Trust This Computer (enter the device passcode if requested). AFC can expose an app document-sharing view containing folders named after apps; this is not the photo library. For photos, install the gphoto2 backend and look for a separate camera/device entry with DCIM, if exposed by the phone. Accept any photo-access prompt. Photos stored only in iCloud may not be available over USB. Access depends on the iOS version and backend support; iOS does not expose unrestricted internal storage.
- Android: unlock the device, connect it with a USB data cable, and select File transfer / Android Auto or MTP in its USB preferences rather than charging-only mode. Accept any file-access prompt. Only storage exposed by the phone is available, not protected system files or private app data.
DEVICES in the sidebar lists the volumes GVfs reports, drives that need a
password before they show a volume, and mounts that have no listed volume. A
mount whose volume is already listed gets no second row. Mounts the system
hides do not appear, such as a Pacman cache subvolume mounted somewhere other
than your home folder, /media, or /run/media/$USER. Plugging in, mounting, unmounting, or removing a device updates it without a
restart, and with nothing to list the DEVICES heading is hidden. Clicking a
mounted volume opens it. Clicking an unmounted volume mounts it, then opens it.
Right-clicking an unmounted volume on a removable drive offers Mount when the
system reports that the volume can be mounted.
Cancelling its password prompt shows no error. Any other failure, apart from a
rejected passphrase or a mount already in progress, shows "Unable to mount
volume" with the system's reason. When another program is already
mounting the volume, Strata shows "Connecting…" and waits up to 8 seconds, then
opens the mount or starts its own mount once.
After installing a backend, fully quit Strata (all windows) and reopen it.
Reconnect the unlocked phone if necessary, then click its entry under DEVICES.
The camera/PTP entry opens a single Photos view: files appear progressively
from storage/date folders, prioritizing newer date-folder names, without requiring
you to open each folder. The backend may finish a folder's metadata before
returning its first batch. This is
a virtual listing of JPEG, HEIC/HEIF, MOV, MP4, and recognized camera RAW files,
not a reorganization of the phone. Sidecars such as .AAE and other formats are
hidden only from this Photos view; their originals remain untouched and visible
in normal folder browsing. Duplicate filenames remain
separate files with their original locations; use Copy path or Properties
to distinguish their sources. Preview, copy, and delete act on those originals.
Deleting a photo removes only its row; a same-named photo from another folder
stays listed.
This is the USB-exposed collection, not iOS's Albums hierarchy. The current
backend does not provide album membership for a reliable Albums/Camera Roll split.
Camera batches yield to interface input and redraws. Photos sorts by Device order by default: batches append in discovery order and are never re-sorted. Device order appears in the sort menu only at a camera root, and there its direction button is disabled ("Device order follows discovery; choose a sort field to reverse its direction"). Choosing Name or Modified sorts the listing; choosing Device order again reloads it in discovery order. The selected photo stays selected while batches arrive. In List view, file-type grouping stays off while Photos loads and while it is in Device order; your saved grouping setting is kept.
Visible thumbnails load top to bottom while the scan runs and are reprioritized after you scroll. A Photos view you have not scrolled stays at the top as batches arrive. While loading, selection updates do not scroll List, Icons, or Columns to the selected photo.
Discovery reads metadata, not every photo's contents. It skips symlinks, avoids revisiting discovered directories, and preserves hidden-file filtering. Photos keeps loading in batches until the whole exposed library is indexed, you navigate away or refresh, or the device reports an error. There is no overall scan deadline or fixed file, folder, or nesting limit. Refresh to rescan after a phone-side change; not every device supports live change notifications.
Android MTP and iPhone app-document/AFC entries retain normal folder browsing. For Android, open Internal storage (the label varies by device).
Still photos (including HEIC) and MOV/MP4 videos can use the preview pane or Space quick preview directly from the phone, without a manual copy. Strata first downloads a private temporary input for sandboxed decoding: up to 64 MiB in 30 seconds for images or 256 MiB in 60 seconds for videos, with at most four staged inputs per process. Video playback waits for that download, then reuses it for seeking and resizing. Closing or changing the preview cancels the request; temporary files are removed after the player and its workers release them. Remote PDFs, GIF images, audio, and video formats other than MOV and MP4 still need a local copy for preview. HEIC decoding requires an installed HEIC-capable image decoder, such as ImageMagick with libheif. Camera/PTP thumbnails use small previews provided by the camera, up to 1 MiB within 15 seconds, with sandboxed decoding; if the camera cannot supply a thumbnail, Strata keeps the file icon instead of downloading the original. Camera thumbnails are cached only in memory. See Remote previews for cleanup, caching, and sandbox details.
If the phone is missing, check the backend package, try another data cable or USB
port, and confirm the trust/file-transfer setting. On Arch/Omarchy, lsusb (from
usbutils) can confirm USB detection, but detection alone does not establish file
access. For iPhone/iPad, also check systemctl status usbmuxd.service while the
phone is connected. If the newly installed backend still is not discovered after
restarting Strata, log out and back in to refresh the desktop's GVfs services.
iPhone appears but photo storage is empty
Some recent iPhones can expose an empty camera/PTP store with libgphoto2 2.5.34, even when unlocked, trusted, and holding locally stored photos. This is a known upstream libgphoto2 issue, not necessarily an empty photo library or a Strata display problem. The backend mishandles the folder-parent information returned by these devices.
Upstream libgphoto2 commit
9f5d4f9
fixes it. Use a distribution libgphoto2 update or backport containing that fix when
available. Merely reinstalling gvfs-gphoto2 or restarting Strata will not fix an
affected libgphoto2 build. Strata's GVfs camera backend must load the corrected
library; setting library paths only for Strata may not affect the separately
launched GVfs process. Strata does not bundle or install the fix. Avoid replacing system libraries manually; any locally built workaround
should be isolated and reversible.
Network shares
Press Ctrl+L, enter an address such as smb://server/share or sftp://user@host:2222/path, and press Enter. Strata uses GIO/GVfs and prompts for credentials when required. If GVfs does not respond within 2 seconds at launch, Strata still opens and prints "GVFS is unresponsive; using local filesystem and volume support for this session." Remote locations are then unavailable until you restart Strata with GVfs responding. Remote protocols need their GVfs backend installed; distributions split these up differently, so check yours for the SMB backend (gvfs-smb on Arch) and the SFTP backend (part of gvfs on Arch, gvfs-backends on Debian and Ubuntu).
When the backend needs credentials, an "Authentication required" dialog shows only the fields it requests. For SMB that can be Username, Domain, Password, a Registered user or Anonymous choice, and Password storage (Don't remember, Until logout, Forever). Anonymous disables the credential and storage fields. Wrong credentials reopen the dialog with "Those credentials weren’t accepted. Check … and try again." Cancel or Escape returns to the previous location with no error and no history entry.
The sidebar's Network place opens network:///, which lists the hosts and
shares GVfs discovers. At smb://host/, opening a share mounts it if needed. A
mounted SMB share appears under DEVICES with a network icon; its menu offers
Properties and Disconnect, and a failed disconnect shows "Unable to
disconnect". An smb:// address without its backend fails with a message naming
gvfs-smb or gvfs-backends. An unknown host, refused connection, timeout, or
unreachable host each shows its own message. Remote entries keep their URI, never
a /run/user/…/gvfs path, and remote names are shown percent-decoded, such as
"My Share" for My%20Share.
SFTP accepts password and SSH-key authentication. Encrypted keys can be unlocked in your SSH agent; if GVfs asks Strata for a key passphrase or host-key decision, Strata presents the request without deciding for you. Trust questions from SMB, other remote schemes, and devices appear in GTK's standard question dialog, not Strata's own. See SFTP locations.
Release channels
Strata defaults to the Stable channel. For release binaries and source builds, only final tagged releases are offered, and a Stable install never receives, sees, or is notified about a prerelease. Package-managed installs follow their package source instead (see Package-managed installations). Stable offers a release only when its tag has no prerelease suffix and GitHub does not mark it as a prerelease. A saved channel value Strata does not recognize is read as Stable.
Strata checks for updates automatically by default: each time it starts, once its first window opens, and again when a window or Settings → Updates opens if no check has completed in the last 24 hours. Turning Check for updates automatically back on, or changing the channel, also runs a check. The check asks the update source for your installation: GitHub for release binaries and source builds, the AUR for AUR packages, the Omarchy package repository for Omarchy packages, or the local pacman sync database for other pacman packages. When a newer version is found, Strata also fetches that release's details from GitHub. Turning the switch off stops the automatic checks, discards the result of an automatic check still running, hides any update notice already shown, and locks the channel. Check now still checks on demand, and the Updates page's release-notes card asks GitHub for the current version's notes when they are not already cached. The installed version's notes are fetched once per tag and kept in ~/.cache/strata/release-notes.toml. Strata never downloads or installs an update without your confirmation.
For release binaries and source builds, the first automatic check of a session
always asks GitHub. Later automatic checks, and the check run by turning
automatic checks on, reuse a result under 6 hours old for the same channel,
stored in ~/.cache/strata/update-check.toml, and
Check now always asks GitHub. Package-managed installs skip this cache and
query their package source on every check. A GitHub 403 or 429 reports "GitHub
API rate limit reached", and any other HTTP error reports "GitHub API returned
HTTP N". A request that gets no response, for example when you are offline,
reports "Network request failed:" followed by the cause.
Update status and notices
- Before a check, the Settings → Updates status row reads "Version X", adding the build kind, such as "Release candidate", for a prerelease build.
- After a check it reads "Strata is up to date", "An update is available", or "Couldn’t check for updates". A failure shows its reason and a "View releases on GitHub" link.
- An available update shows its notes inline, titled "Available release · vX" with its change count and publication date.
- Release notes holds a collapsed "What's new in vX" expander for the installed version, showing "Loading release notes…" until they arrive. Without a GitHub release for that tag, its summary reads "Release notes unavailable for this build", the expander reads "Release notes are unavailable because this version’s tag was not found.", and a View on GitHub link appears. A failed request reads "Couldn’t load release notes: <reason>". Empty notes, or notes holding only HTML comments, read "No release notes were provided for this release."
- Notes show headings, paragraphs, lists, code, and rules. Images, tables, and
block quotes are left out, and raw HTML other than comments, such as
<b>x</b>, shows as text. - HTML comments in notes are hidden, whether inline or spanning several lines.
A body starting with GitHub's `` comment
shows from its first heading. When a comment starts a line, any text after
-->on its closing line is hidden with it; an inline comment hides only itself. A comment that is never closed hides the rest of the notes. - An available update shows a notice in the sidebar of every window, including windows opened later. Clicking it opens the update dialog, titled "Strata vX is available", with "Installed vA → Available vB", the notes under "What’s new", a "View release on GitHub" link, and an action button: Download update for in-place installs, Open Omarchy Update on Omarchy, Open AUR Update or View on AUR for an AUR package, and Close for a pacman install. If the release has no notes, or only HTML comments, the dialog reads "No release notes were provided. Review this release on GitHub before continuing."
To try upcoming changes early, choose a channel in Settings → Updates (the channel is locked while automatic checks are off). Preview receives stable releases plus alpha, beta, and release-candidate builds, but not nightlies. Nightly receives every recognised build, including nightly development builds. For release binaries and source builds, a Stable check reads only GitHub's latest release; Preview and Nightly checks consider the 30 newest releases. The update dialog and release notes always identify the exact build kind.
When a prerelease installation selects Stable, the Updates card immediately offers the newest stable release as the channel target—even when that requires a semantic downgrade—and labels the action Return to stable. Preview and Nightly selections use the same card for ordinary forward updates, so channel changes never create a separate competing rollback card.
Strata offers only tags of the form MAJOR.MINOR.PATCH, with an optional
leading v, optionally followed by -alpha.N, -beta.N, -rc.N (N ≥ 1), or
-nightly.YYYYMMDD[.N]. Drafts and releases
without your architecture's archive are never offered. Outside Return to stable,
only a newer build is offered; for one version, nightly ranks below alpha, beta,
rc, then the final release. A Preview user on 0.5.0-rc.2 is offered 0.5.0.
Return to stable applies only to in-place installs. Its status reads "Stable channel target: vX", the download reads "Downloading stable release…", and success reads "Stable release installed — restart to apply".
Changing the channel clears the sidebar notice in every window and re-checks every open Updates page, except one that is installing or waiting to restart. An open update dialog whose build the new channel excludes reads "This build is no longer offered on your update channel — check for updates again.", and its button becomes Close. Install update on an offer the current channel excludes runs a new check instead.
A prerelease offer shows its build kind as a badge in its notes and in the update dialog, which also lists Channel, Tag, Commit, and Published.
See Releasing for the tag grammar these channels rely on and, for maintainers, how a release candidate is cut and promoted.
Custom actions reference
Custom actions add your own scripts to the file and folder context menus. In 10xer mode, ; then 1–9 / 0 runs the first ten matching actions that can run on the focused item or filled selection; actions whose interpreter or program is missing are skipped.
They are ordinary programs running with your permissions. There is no sandbox and no install step beyond enabling an action. Strata validates the definition and the files around it, prepares private invocation files, and reports progress and results; it does not restrict what a script may do.
Where actions live
$XDG_CONFIG_HOME/strata/actions/
checksums/
action.toml
run.sh
One directory per action, named after its id, containing action.toml and
optionally one script beside it. Settings → Actions creates, edits, duplicates,
imports, and exports these files. You can also edit them by hand. Context menus
and the 10xer ; list reread the manifests each time they open, so hand edits
apply the next time you open one. Once Settings → Actions has been opened in
a window, every window keeps the manifests loaded at that moment until each
window where it was opened closes; closing Settings does not release them. In
that time Strata rereads them only after Settings → Actions creates, saves,
duplicates, imports, or deletes an action, and Save changes or the enable
switch writes the loaded values back over your manifest edits. Restarting Strata
always picks up hand edits. The editor reads the script itself from disk each
time it opens.
Actions are ordinary, user-owned folders under
${XDG_CONFIG_HOME:-$HOME/.config}/strata/actions/. The folder name and manifest
id must match. Use a new lowercase kebab-case id; do not overwrite an existing
action. Create directories with mode 0700 and manifest/script files with mode
0600. Entry points are regular files with plain filenames, not symlinks or
paths. Scripts need no executable bit: Strata invokes the interpreter. Command
actions have only a manifest. Import/export transfers the manifest and declared
entrypoint, not arbitrary helper files. After hand-writing files, restart Strata
if Settings → Actions has been opened since it started, then review and enable
the action in Settings → Actions.
Creating an action
Choose Settings → Actions → New action…. The editor has three tabs:
- General: name, directory id, description, bundled icon, and enabled state. Leave the id blank to derive it from the name.
- Script: choose Python, Bash, or Command. Scripts have a line-numbered editor;
commands take an installed program and one argument per line. Switching runtimes
keeps each script draft until you close the dialog; only the runtime selected
when you save is written. For Python and Bash, a runtime
indicator checks the declared shebang (or default interpreter) against the same executable lookup
used when loading actions. Python uses the script's shebang, or
python3when there is none. Availability is checked automatically when the dialog opens; reopen it after installing a runtime. Bash/Command do not require Python. This does not execute anything or validate script syntax, dependencies such as ImageMagick, FFmpeg, or ExifTool, or behavior; missing runtimes do not prevent saving a draft. - Behavior: execution mode, per-item failure policy, working folder, menu placement, file/folder filters, selection limit, and confirmation. On failure (Continue or Stop) can be changed only when Run is set to Per item.
The editor opens with Name focused, nothing selected, and the caret at the end. Create action saves all three tabs together. Invalid fields bring you back to that tab without discarding your edits. Clicking outside the dialog leaves it open; Cancel, the close button, or Escape discards the draft. Existing actions use the same editor with Save changes; their id stays fixed. Creating or duplicating an action never replaces an existing action directory. Manifest-only MIME filters and minimum selection counts survive editor saves. Command arguments preserve literal whitespace and empty lines; unchanged arguments containing embedded newlines are also retained.
Managing actions
Each action row in Settings → Actions has an enable switch and Edit, Duplicate, Export…, and Delete buttons.
- Duplicate creates
<id>-copynamed “<name> copy”, then tries<id>-copy-1,<id>-copy-2, and so on. - Export… asks for a folder and writes the action to
<chosen folder>/<id>. It refuses if that folder already exists. - Import… asks for an action folder and copies its
action.tomland entrypoint. It saves the action disabled under a free id (<id>, then<id>-1,<id>-2, …) and tells you to review its script before enabling it. - Delete asks Delete this action?, with Delete focused. Confirming removes the action folder and its script from your actions directory.
Script examples
Open Library on the Script tab to browse bundled Python and Bash recipes in a dropdown attached to the editor. Search names, descriptions, requirements, input scope, category, or runtime; every word you type must match. Narrow the list with All, Files, or Media. Each template shows its language, purpose, run mode/input scope, and required tools:
| Example | Extra requirements | Result |
|---|---|---|
| Log selected paths | None | Log paths and report progress without changing files |
| Convert images to WebP | ImageMagick (magick or convert) | First frame, quality 85, in strata-webp-*/converted.webp |
| Resize images to 1024px | ImageMagick (magick or convert) | First frame, aspect-preserving PNG, never enlarged, in strata-resize-*/resized.png |
| Convert videos to MP4 | FFmpeg with libx264 and AAC | H.264/AAC copy in strata-mp4-*/converted.mp4 |
| Extract MP3 audio | FFmpeg with libmp3lame | First audio stream in strata-mp3-*/audio.mp3; fails if there is no audio |
| SHA-256 checksums | None | Adjacent <original-name>.sha256, compatible with sha256sum --check from the original folder |
| Batch rename | Python 3 + Linux renameat2 support | Rename regular files in place with a numbered pattern; never overwrite another name |
| Strip EXIF metadata | Bash + ExifTool + coreutils | Remove writable metadata in place after copying the original into a fresh adjacent strata-original-* folder |
| Lowercase file names | Python 3 + Linux renameat2 support | Lowercase names and replace spaces with dashes, using the same collision-safe engine as Batch rename |
| Count lines | Bash + wc (coreutils) | Log each file's newline count and the total, without changing files |
Python recipes need Python 3 but no pip packages; Bash recipes do not need
Python. Strata does not install tools. A recipe whose ImageMagick, FFmpeg, or
ExifTool command is not on your PATH fails before it creates or changes any
file.
Conversion outputs go into fresh, private folders beside each original;
conversions never overwrite originals. EXIF stripping instead edits the working
photo after making a private backup, as described below. Existing checksum files
and symlinks are refused, not
replaced. A failed or cancelled conversion may leave a partial output folder.
Review scripts and use trusted input files: media tools and actions are not
sandboxed.
Applying a recipe selects its runtime and sets suitable file filters and run mode.
Conversions, checksums, and EXIF stripping select Per item; the starter,
rename/lowercase, and line-count recipes select Whole selection, even if the
previous draft used the opposite mode. A blank Name or Description, or one still
showing the previously applied recipe's text, takes the recipe's name and
description; a name or description you typed, the id, and other settings are
kept. Choose a template to load it into the editor for review; the editor then
shows the Script tab with the recipe loaded. If the target runtime's script is
not blank and differs from the starter template (your edits, an earlier recipe,
or an existing action's script), the dropdown first asks you to Replace
script or Keep draft, without opening another dialog.
Code replacement can be undone in the editor; drafts for the other runtimes are retained.
Escape or clicking outside closes only the dropdown, leaving the editor open.
Searching, browsing, or applying a template never saves or executes it. Review
and save the action, then launch it from its file/folder context menu or, in
10xer mode, ; then a digit. The digits follow context-menu order. A vacant
digit flashes No action N and runs nothing. A digit pressed after the targets
or the action list changed flashes Selection changed or Actions changed and
runs nothing; see 10xer mode.
The documented Python starter and every Python recipe include the same maintained
context() reference as a module docstring.
Examples are starting points: edit the output format, quality, resize limit,
FFmpeg flags, or filters before saving. Shared rename-recipe code is embedded
into the inserted script, so saved recipes do not depend on files in Strata's
source checkout.
EXIF stripping: only regular, non-symlink photos are accepted. Each original is copied completely into a new private folder before ExifTool replaces the working photo; repeated runs keep separate backups. If the backup copy fails, that photo's metadata is left untouched. Failed or cancelled copies may leave partial backup folders, and cancellation does not restore earlier changes. Removing writable metadata can remove orientation/color profiles and is not a guarantee that every format is anonymized. Review results before removing backups.
Count lines: wc -l counts newline characters; an unterminated final line is
not counted. Whole-selection mode gives a total across the supplied selection.
Batch rename
The Batch rename recipe defaults to PATTERN = "{index:03d}_{filename}",
producing names such as 001_photo.jpg. Edit the pattern, or replace
new_name(context) with your own Python logic returning a single filename.
Its per-file context provides:
filename: original name including its extension.stemandsuffix: name without its last extension, and that extension with its leading dot (empty if absent).index: 1-based position in Strata's supplied selection order, not click order;total: number of files in the job.path: original absolutepathlib.Path.batch: the full Stratacontext()object documented below, including logging and progress methods. These per-file fields belong to this recipe, not the general helper.
Patterns accept filename, stem, suffix, index, and total. For example,
"photo_{index:04d}{suffix}" produces photo_0001.jpg. The default whole-selection
mode checks the entire plan before renaming anything. Changing to per-item mode
keeps the job-wide index but can only preflight one file at a time.
Names cannot contain directory separators or be empty, . or ... Duplicate
inputs/destinations, existing destinations (including symlinks), folders, and
symlink inputs are refused. Unchanged names are skipped; swaps into other selected
names are not supported. Every move uses Linux's atomic no-replace operation,
including if another process creates the destination after preflight. Missing
support fails rather than falling back to an overwriting rename. Some filesystems
may refuse case-only changes. Lowercase file names uses the same engine and
safety rules, with an editable new_name(context) transformation instead of a
numbering pattern.
File contents are unchanged, but original names change. This is not an atomic batch or an undo feature: cancellation, concurrent filesystem changes, or an I/O error can leave earlier files renamed. Review the script and try it on copies first.
Manifest
schema_version = 1
id = "checksums"
name = "Generate checksums"
description = "Writes a sha256 file next to each selection."
icon = "file-code"
enabled = true
menu = "submenu"
[when]
kinds = ["file"]
extensions = ["zip", "tar"]
min_items = 1
[run]
runtime = "bash"
entrypoint = "run.sh"
mode = "whole-selection"
on_error = "continue"
working_directory = "parent"
confirm = false
| Field | Meaning |
|---|---|
schema_version | Must be 1. A newer version is refused with an explanation. |
id | Directory name, up to 64 characters: lowercase letters, digits, ., -, _, starting with a letter or digit. It must equal the folder name, or the action fails to load. Cannot change later. |
name | Menu label, 1–64 characters. |
description | Optional accessible description, 1–240 characters. |
icon | Bundled Lucide icon slug, for example play, terminal, image. |
enabled | false keeps the action in Settings but out of menus. |
menu | submenu (default) groups the action under Actions; top puts it in the menu body. |
[when].kinds | file, folder, or both. Empty means either. |
[when].extensions | Extensions without dots, matched regardless of case. Empty means any. |
[when].mime_types | Guessed content types such as image/* or image/png. |
[when].min_items / max_items | Selection size bounds. min_items defaults to 1 and max_items to no limit; both lie between 1 and 10,000, and max_items cannot be smaller than min_items. |
[run].runtime | python, bash, or command. |
[run].entrypoint | Script file name beside action.toml (Python and Bash only). |
[run].program / [run].args | Program and arguments (command actions only). |
[run].mode | whole-selection (default) invokes once with every path; per-item invokes once per path. |
[run].on_error | continue (default) or stop, used by per-item runs. |
[run].working_directory | Where the process starts (Working folder in the editor). parent (default, Invoking) is the invoking folder, which for a folder-background run is that folder itself; home (Home) is your home folder; action (Action) is the action's own directory. |
[run].confirm | Ask once before queuing the entire job (see Confirmation). |
Validation is strict: unknown keys, unsupported versions, invalid ids, entrypoints
that are not a plain file name, and argument tokens that do not match the execution
mode are all refused with a message rather than being ignored. A manifest lists
at most 64 extensions, 64 content types, and 32 command arguments. An extension
is at most 24 characters, with no leading dot, /, \, *, or whitespace.
Matching
An action appears when every currently selected entry satisfies [when], and
the selection size is within min_items/max_items. A mixed selection therefore
never runs an action on a subset the author did not intend to accept.
Extensions match regardless of case, so jpg matches photo.JPG. Content types
are guessed from the file name alone; Strata never reads file contents to match
an action. image/* matches every image/ type.
Opening the folder background menu offers the same rules with the folder itself as the single input. Actions are only offered for native paths: Trash, GVfs, and other non-native locations are excluded in this release.
Custom actions occupy a separate section after the opening, printing, and extract
commands and before Cut/Copy. Actions with menu = "top" are listed first in that
section of the menu body, followed by the Actions submenu row, with a play
icon, holding the rest. Both groups are sorted by name, ignoring case. The context menu uses GTK's native nested menu model: hover over
Actions to open its submenu, then move onto an action to highlight it.
Hovering another menu item closes the submenu. Clicking or keyboard activation
also opens it. On the Actions row, Right, Space, or Enter opens
the submenu with its first action focused; Left closes only the submenu and
refocuses its row. An outside click or Escape dismisses the menu. Long filenames and
paths use middle ellipsis, preserving their beginning and extension.
How an invocation runs
Nothing is ever passed through a shell. Programs and interpreters receive argv
entries directly, and every path is absolute, so a selected file name can never be
read as a command or as an option such as -rf.
| Environment variable | Contents |
|---|---|
STRATA_ACTION_VERSION | Protocol version, currently 1. |
STRATA_ACTION_ID | Definition identity; the display name is in context JSON. |
STRATA_ACTION_MODE | per-item or whole-selection. |
STRATA_ACTION_SOURCE | selection or background. |
STRATA_ACTION_COUNT, STRATA_ACTION_POSITION | Input count, and 1-based position for per-item runs. |
STRATA_ACTION_PATHS | File containing every input path, NUL-delimited and byte-exact. |
STRATA_ACTION_PARENT | File containing the invoking folder. |
STRATA_ACTION_PROGRESS | File to append progress events to (see below). |
STRATA_ACTION_CONTEXT, STRATA_ACTION_RUN_DIR | JSON context and private scratch directory, mode 0700. |
STRATA_ACTION_DIR | The action's own directory. |
Paths travel in files rather than in the environment so unusual names — spaces, newlines, and bytes that are not valid UTF-8 — survive exactly.
For a Bash script, the manifest's [run] section uses runtime = "bash",
entrypoint = "run.sh", and mode = "whole-selection". Example run.sh:
#!/usr/bin/env bash
set -euo pipefail
while IFS= read -r -d '' path; do
printf 'Selected: %q\n' "$path"
done < "$STRATA_ACTION_PATHS"
STRATA_ACTION_PATHS is the name of a file containing NUL-delimited paths,
not a whitespace-separated list. Always quote paths; never use for path in $(cat ...) or eval. STRATA_ACTION_COUNT is invocation-local;
STRATA_ACTION_POSITION is the 1-based per-item position. The invoking folder is
stored byte-exactly in the file named by STRATA_ACTION_PARENT.
whole-selection runs the action once with every selected path. per-item runs it
once per path and tracks succeeded, failed, and remaining counts itself; with
on_error = "stop" the first failure ends the job.
Confirmation
With confirm = true, choosing the action opens Run this action? with the
action's name and icon. It reads “This runs “<name>” on <n> selected items.”, then
the action's description, with Run focused. Cancel or the close button
runs nothing.
Command argument tokens
args entries are either literal text without { or }, or exactly one of:
{path}— the single input of a per-item run.{paths}— every input of a whole-selection run, as separate arguments.{parent}— the invoking folder.
Any other argument containing a brace, such as prefix-{path} or {}, is
refused, so nothing is ever interpolated into a command line. Use a Bash action
if a program needs literal braces.
For an installed executable, [run] looks like this—no script file:
[run]
runtime = "command"
program = "sha256sum"
args = ["--", "{paths}"]
mode = "whole-selection"
Programs receive direct argv, not shell source: pipes, redirection, $VARIABLE,
and globbing are not expanded. Use Bash if shell syntax is needed.
Progress and results
Process exit status decides success: 0 means the invocation succeeded and any
other status means it failed. Reported percentages are presentational only.
A script may optionally report measurable progress by appending one JSON object per
line to $STRATA_ACTION_PROGRESS:
{"event": "progress", "processed": 42, "total": 100, "message": "Converting images"}
{"event": "output", "path": "/home/you/Pictures/out.webp"}
processedis required and bounded;totalandmessageare optional.outputrecords a created location: absolute paths only, which is why a relative path is ignored rather than guessed.- Malformed or unknown lines are ignored, the file is read incrementally, and both the file and the number of events per invocation are bounded.
Whole-selection scripts that never report a total still appear as Running with elapsed time and an indeterminate indicator. A per-item job's bar fills by completed items, plus the current item's reported fraction. stdout and stderr are captured as bounded output for the Jobs dashboard; they are not the progress channel.
Python helper
Python actions can use the bundled standard-library helper, which is importable
inside a run and needs no pip install. In this sketch, convert stands for your
own function that writes <path>.webp:
#!/usr/bin/env python3
from strata_actions import context
ctx = context()
for index, path in enumerate(ctx.paths, start=1):
convert(path)
ctx.progress(index, len(ctx.paths), "Converting images")
ctx.output(f"{path}.webp")
ctx.paths are str values decoded with surrogateescape, so use
ctx.paths_bytes() when a tool needs the original bytes. ctx.single returns
the sole path for a one-item invocation, or None. ctx.count counts inputs in
this invocation, not the entire per-item job. ctx.position and ctx.total are
the 1-based job position and job size in Per item mode, otherwise None;
whole-selection scripts enumerate ctx.paths themselves.
A script that only logs the selection, as main.py with runtime = "python" and
entrypoint = "main.py":
#!/usr/bin/env python3
from pathlib import Path
from strata_actions import context
ctx = context()
for index, path in enumerate(ctx.paths, start=1):
ctx.log(f"{index}: {Path(path).name}")
ctx.progress(index, ctx.count, "Logging selected files")
Other properties are parent (invoking folder, not necessarily the working
directory), directory (action directory), run_directory (private scratch,
removed after the invocation), action_id, version, metadata (raw JSON),
mode, source, and the optional 1-based per-item position and total.
ctx.log(message) writes to captured stdout. Bytes that are not Unicode
are escaped, so logging a native path still succeeds when the locale uses a
strict UTF-8 stdout. ctx.progress(processed, total=None, message=None) reports invocation-local work; ctx.output(path)
reports an absolute output path, but does not create a file. Output reporting is
best-effort: names containing non-UTF-8 bytes cannot be represented by the JSON
progress channel and produce a warning rather than failing the action.
Import find_tool(name) to look up an executable (returns its path or None), or
require_tool(name) to raise ContextError when a dependency is missing.
Any other language can follow the same contract: read the paths file, write the progress file, and exit with a status.
Jobs and cancellation
Each invocation runs in the background. Queuing an action automatically opens Jobs in the launching window, with that new job first, showing its queued/running state, progress, and elapsed time; Details shows its output. Confirmation actions open Jobs only after you choose Run. This presentation does not change queue execution order or open dashboards in other windows. A Jobs button appears in the footer only while jobs exist. It reads, for example, “2 jobs running · 1 queued”, or “3 jobs finished” when none are active, with “ · failures” added when any job failed. Clicking it reopens the dashboard.
Minimizing, pressing Escape, or clicking away only hides the dashboard. Progress and completion updates do not reopen it; launching another action does. Remove on a queued job ends it as Cancelled (“Removed before starting”) without running it. Cancel on a running job shows “Cancelling…” and sends SIGTERM to its whole process group, then SIGKILL after 2 seconds. A job still cancelling after 10 seconds is marked Cancelled (“Cancelled; the action did not stop cleanly”) and frees its slot. Closing the last application window while jobs are queued, running, or cancelling shows Background jobs are still active and keeps the window open; finish or cancel them in Jobs first. Other windows may close without interrupting work.
An invocation ends when its direct process exits. Output capture and scratch files are then closed without waiting for background descendants. Scripts should wait for subprocesses that need the invocation's context or captured output.
Up to 20 finished jobs (successes, failures, and cancellations) stay for the
current session. The oldest finished jobs are dropped first; active jobs never
are. The dashboard lists at most 12 jobs, then shows “<n> older jobs are hidden”.
Details expands captured output and Hide collapses it; a queued job has no
Details yet. Details shows “No output yet.” until output arrives. On a running
job it streams new output and follows the bottom until you scroll up, then follows
again once you scroll back down. The header summarizes running, queued, and
finished jobs. Each row shows the action's name and icon, a theme-accent status
(“Queued”, “Cancelling…”, or “Running for”, “Done in”, “Failed after”, or
“Cancelled after” with the elapsed time), and a check or X for finished results.
Below it, the row lists the script's latest message, progress counts such as
3/10 (plus “<n> failed” in a per-item job), and the invoking folder, shown as
Home or ~/… under your home folder. Failure
output appears only in Details, not a separate banner.
The dashboard opens above the footer without covering it.
Icon-only buttons retain tooltips; controls retain accessible names. Minimize keeps history;
Dismiss removes one finished job,
and Clear finished removes finished history without disturbing active work.
Cancelling stops the work that has not happened yet. It does not roll back changes already written to disk, and Strata does not retry a failed or cancelled action.
Trust model
- Actions are trusted local programs. Out-of-process execution is not a filesystem or network boundary; a script can do anything you can do.
- Imported actions arrive disabled. Review the script before enabling it.
Import copies only
action.tomland its entrypoint. - Strata never discovers or runs scripts found in browsed folders, and never installs runtimes, interpreters, or packages. A missing interpreter or program leaves the action visible but disabled, with the reason in its accessible description.
- Interpreters and programs are looked up on your
PATH. A script without a shebang runs withpython3orbash. A shebang outside the runtime's family, such as#!/bin/bashin a Python action, makes the action fail to load and appear under PROBLEMS. Aprogramwritten as a relative path containing/counts as unavailable; use a bare name or an absolute path. - Manifests and generated scripts are written owner-only (0600) inside an owner-only directory, and entrypoints are read as regular files: a symlinked manifest, entrypoint, action directory, or scratch directory is refused rather than followed.
- Each invocation keeps the newest 8 KiB of stdout and stderr, starting with “…” when trimmed, and a job keeps the newest 64 KiB across invocations. Terminal colour and control sequences are stripped, and the rest is shown as plain text.
Limitations
- Local native locations only; Trash, remote mounts, and the file chooser are out.
per-itemruns are sequential, and at most two jobs run at once.- Whole-selection commands that cannot report progress show no percentage.
- There is no sandbox, no restart/resume, and no built-in parameter form; a script that needs options reads them from its own file or environment.
- Editing an action's script from Settings replaces the whole file; keep large scripts in version control if you edit them outside Strata.
Testing an action
Enable it, then right-click a file that matches [when] and choose it. The Jobs
dashboard shows the invocation, its output, and its exit status. A definition that
cannot load appears under Settings → Actions → PROBLEMS as
<folder>: <reason>, and never silently disappears from the menus; the other
actions still load. PROBLEMS carries the note “These files could not be loaded.
Fix them in the actions folder, or remove them.” Settings search finds the action
list and PROBLEMS as “Custom actions”, New action… as “New custom action”,
and Import… as “Import custom action”.
When a coding agent writes an action for you: choose a fresh id, write the matching manifest and entrypoint, declare required tools, preserve originals/refuse overwrites, and keep the action disabled for review. Test on disposable copies through Strata's context menu, then inspect Jobs output.
Service-dependent actions and badges
For asynchronous eligibility based on external state and live file decorations, see External file providers. Static action matching remains limited to the file/selection filters described above; a provider can keep its menu entirely absent outside the locations it supports.
Themes reference
Strata styles the interface with nine semantic color tokens. Bundled themes are the fallback on any Linux desktop. A fresh install without Omarchy starts with Tokyo Night, and the saved selection survives restart. If the saved theme matches no bundled or custom theme, Strata falls back to Azure Glow at startup.
Open Settings with the header Settings button or Ctrl+,, then choose Appearance. Under THEME LIBRARY, Strata lists the 95 bundled themes in alphabetical order in one scrolling library. Typing in Search themes hides cards whose names do not contain the query, ignoring case. In Search themes, Ctrl+A selects the query on any keyboard layout; Ctrl+Shift+A, Ctrl+Alt+A, and Ctrl+Super+A do not. The All, Light, and Dark filter combines with the query. A theme counts as Light when its background's relative luminance exceeds 0.4, whatever color form the background is written in.
Clicking a card applies the theme immediately across the interface, marks the card with a check, and keeps that theme active across restarts. While Follow Omarchy is on, the library is disabled; turn off Follow Omarchy to pick a theme.
Tinted Base16 entries map colors to Strata tokens as follows: base00 to background, base01 to surface, base05 to text, base0D to accent, base08 to danger, base02 to muted and highlight, base03 to border, and base04 to dim text. Every bundled theme's text has at least 4.5:1 contrast on its background and 3:1 on its surface. A few bundled entries override the mapped foreground values to meet that: Material Lighter draws text in #455A64 (6.94:1 on its background) and dim text in #607D8B, and Material Vivid draws text in #9e9e9e (6.01:1). Where the upstream dim text is also unreadable, it is adjusted to stay legible while remaining dimmer than text. The catalog comments each override next to the value. Source revision and licensing details are recorded in THIRD_PARTY_LICENSES.md.
GTK CSS precedence
Strata defines its nine named colors as @strata_bg, @strata_surface,
@strata_text, @strata_accent, @strata_danger, @strata_muted,
@strata_highlight, @strata_border, and @strata_dim_text. These replace the former
@theme_* names; user stylesheets referencing those names must be updated.
Custom theme TOML keys are unchanged.
Strata's token provider takes precedence over GTK theme defaults, but user
~/.config/gtk-4.0/gtk.css retains GTK's higher user priority. The namespace
prevents accidental collisions with other stylesheets' @theme_* colors;
it does not override deliberate user selectors or @strata_* definitions.
User CSS that redefines the former @theme_* names no longer changes Strata's
colors.
Element glow, motion, and renderer
Settings → Appearance → EFFECTS → Element glow is on by default and saved
as element_glow = true. It adds accent glow to dialogs, menus, theme cards,
and animated feedback. The video preview's
ambient light, and the 24 px band it needs
around the frame, follow the same switch, live in an open preview.
Turning it off removes that glow in every window at once, keeps focus
outlines, depth shadows, and animation movement, and persists across restarts;
use Reduce motion to stop animations.
Settings → Appearance → MOTION → Reduce motion stops sidebar, column, and
preview animations. GTK's gtk-enable-animations set to false stops the same
animations even when Reduce motion is off. Strata's stylesheet ignores the
desktop's prefers-reduced-motion media preference.
Settings → Appearance → RENDERING → Interface renderer offers
GTK default, the initial choice, and Cairo, saved as
interface_renderer = "system" or "cairo". Cairo avoids text artifacts on
some displays but can use more CPU. Choosing a value other than the one Strata
started with shows Restart now; the change applies only when a new Strata
process starts. Restart now closes every Strata window and starts Strata
again; while a file operation or drive format runs, the usual close warning
appears instead and nothing restarts. Without the button, quit Strata by
closing all of its windows, then reopen it: closing one window while others stay
open keeps the old renderer. The choice and Restart now stay in step across
open Settings windows. A GSK_RENDERER environment variable set before Strata
starts, even to an empty value, overrides the saved choice. When Strata selects
Cairo itself, applications it launches may inherit that renderer; desktop
settings are unchanged.
Icon colors
Interface icons in the header, sidebar, and Settings navigation, and Lucide file-type icons, draw in the theme's accent at full opacity. Destructive menu items, such as Permanently delete, and danger-tone dialogs draw their icon in the danger color. Changing the theme or Omarchy variant recolors icons, including Catppuccin file icons, in every open window.
Settings → Appearance → FILE ICONS → File icon colors offers
Brand colors, the default, and Theme colors. The choice is saved as
file_icon_colors = "brand" or "theme", a missing key reads as Brand colors,
and a change applies in every open window at once. Typing
"catppuccin", "brand palette", or "monochrome" in Search settings finds
this row.
- Brand colors draws Catppuccin file icons in their own Mocha palette on dark backgrounds and Latte on light ones. A background counts as dark when (299R + 587G + 114B) ÷ 1000 is below 128, or when it cannot be parsed.
- Theme colors draws every color of a Catppuccin icon in the accent and gives unfilled shapes a 15% accent fill, like the folder icon.
- Neither choice changes interface icons, Lucide file-type icons, or folders.
A code file such as main.rs with a custom color saved in Customize and no
custom icon keeps its brand palette under Brand colors; under Theme colors its
icon takes the saved color instead of the accent.
File-type icons
Code and config files, including JSON, YAML, XML, SQL, database, .toml, and
Markdown files, show Catppuccin icons, such as the Rust icon for main.rs, the
package-json icon for package.json, and the Cargo icon for Cargo.toml.
Pictures, plain text, spreadsheets, and keys keep Lucide icons, such as
photo.png, photo.svg, notes.txt, report.csv, server.pem, and
id_ed25519. Search results use the same icons as the Columns, List, and Icons
views.
Strata picks a file's icon in this order:
- An exact file name, ignoring case.
Makefile,MAKEFILE,Dockerfile,Cargo.lock,vite.config.ts,README, andLICENSEeach have their own Catppuccin icon.docker-compose.override.ymlandcompose.yamlshow the Docker Compose icon. Shell rc files such as.zshrcand.BASHRCshow the Bash icon. - A case-sensitive name pattern.
Dockerfile.*shows Docker,.env.*env,tsconfig.*.jsonTypeScript config,*_historya terminal file, and*.lockthe Lucide cog. - The longest matching dotted suffix, so
types.d.tsandapp.test.tsshow specific icons, not the.tsicon, anddeploy.ymlshows the YAML icon. - A built-in extension list. An unrecognized extension shows the document icon.
Some results of that order:
archive.lockshows the Lucide cog, whileARCHIVE.LOCKshows the Catppuccin config icon..mshows MATLAB and.vshows V..s,.asm, and.nasmshow assembly;.ps1PowerShell;.sv,.svh, and.vhdlVerilog;.batand.cmdBatch. Shell scripts show Bash..qml,.tcl,.qrc, and.uishow the generic code icon.app.apkshows Android andapp.jarJava archive..nupkgand.vsixshow Catppuccin icons;.deb,.rpm, and.exekeep the Lucide package icon..mp4,.mkv,.webm,.mov,.avi,.m4v,.mpeg,.mpg,.ogv,.3gp,.3g2,.flv,.wmv,.asf,.m2ts, and.vobshow the Lucide clapperboard..zip,.7z,.tar,.gz,.tgz,.bz2,.xz,.zst,.rar,.lz,.lzma,.lzo,.rz,.sz,.cab,.arj, and.cpioshow the Lucide folder-archive icon, distinct from documents.- Spreadsheets, presentations, fonts, disk images, and keys each show their own Lucide icon.
Icon size and weight
Header-bar and pane action icons draw at 16 logical px at the default text size, centered even when the desktop theme gives buttons extra space. Chrome icons rasterize at twice their logical size; file, sidebar, and dialog icons rasterize at 96 px or their device-pixel size, whichever is larger. Icons rasterize at the display's pixel density, so 2× displays get sharp strokes.
In the Icons view, Lucide outlines draw at half the stroke weight used in List rows, toolbars, and the sidebar. Above 64 logical px, strokes thin further by (64 ÷ size)^0.35, about 0.62× at 256 px, so large icons do not read as bold. Catppuccin file icons take the same factor and halving: in the Icons view their strokes match the folder icon beside them, and in List rows they draw at three quarters of its weight.
Custom theme files
Custom themes are TOML files in:
~/.config/strata/themes/<theme-id>.toml
Under the library, Strata shows "Custom themes live in ~/.config/strata/themes" and an Add theme button. Add theme opens the Add a theme panel with a name field and 14 color pickers seeded from the selected theme: nine for the background, surfaces, text, accent, danger, muted and highlighted elements, borders, and dimmed text, and five for syntax colors. Strata previews edits live. Add theme in the panel saves the theme as a new file, created owner-only (mode 0600), and selects it. The new theme also appears in the theme library of Settings open in other windows, without a restart. Saving with an empty or whitespace-only name shows "Enter a theme name" and writes nothing. The editor's color swatches keep rounded corners, with no square fragments, whether normal, hovered, focused, or pressed.
The settings configurator writes the same format, so generated themes can be edited or shared:
name = "Ocean Blue"
background = "#0c1a2b"
surface = "#122438"
text = "#c9deed"
accent = "#4fd6ff"
danger = "#ff6b7a"
muted = "#1e3a52"
highlight = "#244d68"
border = "#315b75"
dim_text = "#6f8da3"
Strata loads valid .toml files in this directory at startup and lists them in the theme library after the bundled themes, keyed by file name without .toml. If a custom filename matches a bundled theme ID, the custom theme replaces that bundled entry so saved preferences and selection always use the user’s palette. Colors load as #rrggbb, or #rrggbbaa when translucent, so GTK-only forms such as 9-digit hex still apply; the file is not rewritten. Icons, both interface and file-type, draw an opaque form of the accent, text, or danger color, so a translucent color loses its alpha on icons only.
The configurator derives a new file's ID from the theme name, lowercased, keeping ASCII letters and digits and joining the rest with - (for example Ocean Blue becomes ocean-blue.toml). Names without ASCII letters or digits are saved as custom-theme.toml, the next such name as custom-theme-2.toml, then custom-theme-3.toml. The name field keeps the typed name, trimmed of leading and trailing spaces, so names such as 日本語 are still shown as written.
Theme files may be symlinks into a dotfiles repository. The configurator never replaces an existing theme: when the ID matches a bundled theme or a loaded custom theme, or <theme-id>.toml already exists, whether it loaded or not (for example an invalid file or a link to a missing or broken dotfile), the new theme is saved as the next free <theme-id>-2.toml, <theme-id>-3.toml, and so on. Saving a theme named Dracula therefore creates dracula-2.toml and leaves the bundled Dracula theme in place.
Syntax colors
All 95 bundled themes include explicit code-preview palettes. Tinted Base16 palettes map base0E to keywords, base0B to strings, base09 to constants, base0A to types, and base0C to preprocessor directives. Catppuccin and Tokyo Night use the pinned catppuccin-mocha and tokyo-night-dark syntax palettes; Azure Glow and Omarchy Light have original curated palettes.
Under Settings → Appearance → Add theme, the syntax color pickers in the Add a theme panel start with the selected theme's colors. Each picker previews changes immediately across the interface and in open code previews; Cancel restores the selected theme, and Add theme saves all five syntax colors with the interface palette. Closing Settings by any route (Escape, Close settings, a click outside it, or closing the window) discards an unsaved preview the same way and collapses the editor. A discarded preview re-applies the saved theme in every open window and in windows opened later. Pressing the library's Add theme button again while the editor is open keeps the draft. Opening the editor again starts from the selected theme's colors, with an empty name and no error. Changing text size, toggling Element glow, or an Omarchy theme change while following keeps the preview until it is cancelled or saved. Clicking a theme card or toggling Follow Omarchy ends the preview. If followed Omarchy state disappears during a preview, the preview ends and the previously selected bundled or custom theme applies. Cancel, or closing Settings, in one window leaves a preview started later in another window applied. Dim text / comments controls comments as well as dim interface text. Markdown headings continue to use the accent color. Rendered 3D model previews, such as STL files, are shaded in the theme's accent, and an open model preview re-renders when the theme changes; see Local 3D model previews.
Each color swatch in the editor opens GTK's color chooser. Its Cancel and Select buttons and its custom color editor (hex entry, hue slider, and the value popups) follow the active theme and update live, as does the same chooser in the custom folder color dialog.
Custom TOML files can override any syntax role independently:
syntax_keyword = "#ff7b72"
syntax_string = "#7ee787"
syntax_constant = "#79c0ff"
syntax_type = "#ffa657"
syntax_preprocessor = "#d2a8ff"
Recognized source languages keep syntax highlighting regardless of the loaded text's byte count, line count, or individual line length. Source text still loads incrementally, and the separate 1 MiB preview-read cap remains in effect. Text without a recognized language opens in a source view, without syntax colors, up to 128 KiB and 512 lines with no line over 2 KiB. Larger files, and files with a longer line, use recycled plain-text rows; see Document previews.
All color fields, the interface colors included, accept GTK color formats such as rgb(), short hex, and color names; a theme written that way keeps its syntax colors in code previews. An omitted syntax_* key uses a color derived from accent and text, and an omitted danger uses #e5484d. Every other color key and a name are required, and the name must contain a non-space character: a file missing one, or with a blank name, is skipped at startup. The editor initializes omitted syntax fields from those derived colors when creating a theme, and writes each picked color as #rrggbb. Invalid colors cause a custom file to be excluded at startup. Preview schemes canonicalize colors to opaque #rrggbb.
Omarchy Quattro
On Omarchy Quattro, turn on Follow Omarchy under Settings → Appearance. Strata detects the active theme from:
~/.local/state/omarchy/current/theme.name
~/.local/state/omarchy/current/theme/colors.toml
The application maps Quattro's background, foreground, accent, selection, color8, and color1 values into its semantic tokens and monitors the current-theme state for changes, including edits to colors.toml. It defaults to following Omarchy on first launch, when no settings.toml exists. While following, the theme library is disabled and Current theme reads "Managed by Omarchy. Turn off Follow Omarchy to pick a theme manually."
Under Settings → Appearance → Follow Omarchy, Omarchy variant offers:
- Original (default): the existing palette mapping, unchanged.
- Darker: dark surfaces based on the terminal background instead of the brighter ANSI gray, with readable text and accents. Light palettes also become dark interpretations.
- High contrast: stronger text and boundary contrast, retaining a light palette's light appearance or a dark palette's dark appearance.
The variants keep palette hues and adjust brightness where necessary; they do not invert colors or substitute another theme. Darker and High contrast derive muted/hover surfaces from the same palette, adjust semantic foregrounds for at least 4.5:1 contrast against those surfaces, and adapt preview syntax colors. High contrast targets 7:1 for primary text and 3:1 for borders. These are semantic-token targets, not a guarantee for every composited or disabled widget state.
The choice is saved as omarchy_variant = "original", "darker", or "high_contrast" in Strata's settings.toml. A missing or unrecognized omarchy_variant value reads as Original, and the other saved preferences are kept. It applies before Settings opens and live across windows, menus, dialogs, icons, and previews. Changing the active Omarchy theme retains the variant. Turning off Follow Omarchy disables the selector but remembers its value. Variants never change bundled or custom themes or the desktop theme.
Syntax colors follow Quattro's named magenta, green, orange, cyan, and yellow colors. Older terminal palettes can supply color5 for keywords, color2 for strings, color9 for constants, and color3 for types. Missing colors retain the existing source-palette or derived fallback. Quattro values load in the same canonical hex form as custom theme files; values GTK cannot parse count as missing.
Follow Omarchy and Omarchy variant are shown only when both files exist and colors.toml has valid background, foreground, and accent colors. An invalid optional selection or color8 is ignored and its fallback used. If that state disappears while Strata is running, Follow Omarchy is hidden, following turns off (saved as mode = "theme"), and Strata returns to the previously selected bundled or custom theme. Omarchy's own theme switch, which briefly removes current/theme, does not turn following off. If it only becomes invalid, for example midway through an Omarchy theme switch, the last applied Omarchy palette stays in use until the next valid change. Legacy Omarchy theme layouts and alacritty-based color extraction are intentionally unsupported.
Keyboard navigation
Columns have three independent signals:
- Selection: filled rows are the items selected in that directory. Other columns retain a quieter selection when you leave them.
- Keyboard cursor: a text-contrast outline identifies the current item in the keyboard-focused list. Only that list shows a cursor; range selections can contain several filled rows.
- Open path: the chevron identifies the folder whose child column is open, without an extra border. This is navigation context, not another keyboard cursor.
The column that Ctrl+V will paste into has an accent rule across its header, including when the directory is empty. It moves to the column under the pointer as soon as you move the pointer. Columns fill the strip's full height.
Keyboard layouts
Shortcuts on this page work on any keyboard layout, with the exceptions below.
Letters follow the key's label, or the Latin letter the key carries on Russian and
other non-Latin layouts, so Ctrl+C is the key that types с in Russian. On
plain Chinese (cn), every shortcut is the US one. Digits count by their position
on the top row, so Ctrl+1 works on AZERTY without Shift. A digit typed off the
top row also counts, such as the Hungarian 0 left of 1. Caps Lock never changes a
shortcut. A symbol shortcut follows the symbol your layout types. A key that types
another ASCII symbol keeps it: on AZERTY, Ctrl and the key in the US . position
is not Ctrl+.. Where a key types a non-Latin or accented character, it also acts
as the Latin character on that key in another configured layout, or in its US
position when no configured layout is Latin: on Russian, Ctrl and the key that types
ю act as Ctrl+. and toggle hidden files.
With Type to search on, a key that types a letter starts type-to-search with that letter, even in the US / position: on Icelandic the key that types þ starts type-to-search with þ instead of opening an empty filter. Plain-key commands still read the key's Latin character: in 10xer mode on Russian, the keys that type о and л move the cursor like j and k, and on German ö in the file list arms the actions chord as ; does.
The exceptions: where a top-row key types + or −, Ctrl with that key acts as
Ctrl++ or Ctrl+−, not as the digit, and in 10xer mode g reads it as + or
− too: on AZERTY g, then the − key unpins. Swiss German types + with Shift+1, so
there Ctrl+Shift+1 selects no tab. With AltGr held, a top-row key counts only as
a digit it actually types, so AZERTY Ctrl+AltGr+1 is not Ctrl+1.
Ctrl+\ also works on German, Swiss, Swedish and Norwegian Mac layouts, where
AltGr types \ on the top row. t and ; in 10xer mode have no + or − step,
so after them a top-row key counts by its position even where it types + or −: on
AZERTY t, then the − key selects tab 6, and on Czech t, then the + key
selects tab 1.
Letter, digit and symbol shortcuts match Ctrl, Alt, Shift and Super exactly, so Ctrl+Alt+C does not copy. Chord digit steps, such as t, then 1 in 10xer mode, and the media 0 key also accept Shift. Some navigation and dismiss keys accept extra modifiers: Delete and Shift+Delete still act with Ctrl, Alt or Super held, and Escape closes a dialog whatever else is held. Hyper and Meta are ignored. A symbol shortcut ignores the Shift your layout needs to type the symbol. Keypad Enter, arrows, Home, End, Page Up, Page Down, Insert, Delete, Tab, Space, +, −, *, / and = act as the main keys; keypad digits count only with Num Lock on.
Typing is never remapped: type-to-search, the filter, rename fields and footer prompts receive the characters your layout types, such as Cyrillic. While a text field shows an unfinished input-method or dead-key composition, keys go to the composition before any Strata command. A Korean input method such as fcitx5-hangul commits the syllable on Escape and passes the key back, so one press commits the syllable and cancels a rename. Type-to-search started from the file list does not use your input method: a pinyin letter arrives as the Latin letter, and a dead key starts nothing. To search with an input method, open the filter with Ctrl+F (f in 10xer mode) and type there.
Every shortcut Strata shows is one that works. Shown shortcuts in F1, menus and tooltips stay in Latin letters when you switch layouts. Modifiers appear in the order Ctrl, Alt, Shift, Super, and a letter after a modifier is uppercase, as in Ctrl+Shift+N. Without a modifier, a letter appears as typed (j) and Shift with a letter as the uppercase letter (J). Chord steps are separated by a space (g h). Alternatives that share their modifiers write them once, as in Ctrl+Alt+← / → and Ctrl++ / − / 0, unless a key is a letter (Ctrl+U / Ctrl+D). Digit ranges read Ctrl+Shift+1–9 / 0 or t 1–9 / t 0. Minus is written −, and arrows ↑ ↓ ← →. Key names follow the interface language, such as Strg+C, Entf and Bild auf for Page Up in German, or Suppr for Delete in French; with the interface in Simplified Chinese they stay as printed, such as Ctrl+C.
Browser tabs
In regular and 10xer modes, Ctrl+T opens a tab at the active location, Ctrl+W closes the active tab, and Ctrl+Tab / Ctrl+Shift+Tab cycles tabs. Ctrl+Page Up / Ctrl+Page Down selects the previous / next tab in strip order, wrapping at either end, like the tab shortcuts in web browsers. Ctrl+Shift+Page Up / Ctrl+Shift+Page Down moves the active tab one position left / right without switching tabs. Reordering stops at either end of the strip. With Alt or Super also held, these Page Up and Page Down shortcuts leave the tabs alone. The moved tab keeps its location, selection and focus, including focus in the location editor. Hold Ctrl+Shift, without Alt or Super, to display numbers beside the first ten labels; they hide when you release Ctrl or Shift or the window loses focus. Press Ctrl+Shift+1–9 to select tabs 1–9 or Ctrl+Shift+0 for tab 10. In 10xer mode, t, then n creates a tab, t, then x closes it, and t, then 1–9 / 0 selects tabs 1–10. t, then t selects the previous tab in strip order, wrapping from first to last. Escape cancels a pending chord. The last tab's close shortcut closes the window. New tabs are added at the right end of the strip. Closing the active tab selects the tab to its right, or the one to its left when it was last. The regular-mode terminal shortcut is Ctrl+Alt+T; 10xer keeps ;, then t. Tab shortcuts do nothing while a dialog is open.
In both key maps, Ctrl+Enter on a focused folder opens it in a new tab and Shift+Enter opens it in a new window; keypad Enter works too. In the default map, Ctrl+Shift+Enter on a folder also opens a tab; in 10xer mode it does nothing. The file chooser opens no tab or window: there Ctrl+Enter from the file list chooses the folder in a folder request, or confirms the destination in Move to, Copy to and Extract to. In a text field, these keys go to the field. On a file, both open it with its default application, like Enter. With the pointer, middle-click a folder in Columns, Icons or List to open it in a new tab, or Ctrl+middle-click or Shift+middle-click to open it in a new window; middle-clicking a file only selects it. Open in… → New Tab or New Window in a folder's menu does the same. With several items selected, including at least one folder, Open in… → New Tab or New Window opens one tab or window for each selected folder and skips files. Selecting a tab returns focus to the control that last had it in that tab, or to its file view's cursor when that control is gone.
Each tab retains its location, selection, navigation history, preview and search
state. Tab locations persist across restarts: a plain launch (no folder
argument, reveal request, or unlock target) reopens the previous tabs in order
with the previously active tab selected, when Settings → General → STARTUP →
Restore open tabs is on (the default). The session is saved in
$XDG_CONFIG_HOME/strata/tabs.toml, which turning Restore open tabs off
deletes. Missing directories, relative paths, local folders whose path is not
valid UTF-8, URIs that carry a
password (a user name alone, as in smb://user@server/share, is kept), locations
inside Trash, and Recent entries other than its root are skipped. So is every scheme
other than smb, sftp, ftp, ftps, dav, davs, trash, network and
recent, such as camera roots (gphoto2://) and mtp:// devices. With nothing restorable the window opens
at the default directory as before. Up to 32 tabs are restored. When the saved
active tab is skipped, the nearest restored tab to its left is selected, or the first
tab when none is to its left. A saved active tab beyond the last restored tab selects
the last one. Windows opened for an explicit folder,
reveal request, or unlock target never overwrite the saved session; with
several plain-launch windows open the most recently changed one wins. Selection, history, and preview state stay
in-memory. Appearance preferences and the clipboard remain
shared. File operations prevent closing their tab or window until they finish
or are cancelled.
Tab names follow the active directory, not a child column shown only as a keyboard
preview: ~ for your home folder, / for the root, Trash, Recent and
Network for those places, and names longer than 22 characters are cut short with
an ellipsis. On a remote location the name changes only once the new location
answers; a refused or replaced navigation keeps the previous name. A pending single-click folder activation keeps the previous tab name until
navigation resolves; cancelled clicks and drags restore normal focus-based naming.
The Material-style strip appears when there is more than one tab. The plus and window-close controls move into it and return to the normal header when only one tab remains. Scroll the strip horizontally (or use the wheel) when it outgrows the window; selecting a tab brings it into view without a scrollbar. Drag a tab label to reorder tabs. Drop files on a tab to transfer into its current directory, or hover there during a file drag to switch tabs and choose a folder in its listing. Existing copy/move modifiers and conflict handling apply.
Input precedence
With exactly one folder explicitly selected, Ctrl+V pastes into that folder. A folder selected for you when its directory loaded does not count: the folder you came from after Up, Back or Forward, a restored selection, or the first item selected on arrival. In those cases, and with a file, several items, or nothing selected, the last navigation input determines the destination column:
- Moving, clicking, or scrolling the pointer restores pointer control. Paste targets the directory column under it, not an individual hovered file or folder.
- Keyboard navigation (arrows, h/j/k/l, Tab, page movement, entering/leaving folders) or Select All restores keyboard control. Paste targets the focused column, falling back to the active column when browser widgets do not hold focus.
- Ctrl+V itself does not change ownership. A parked pointer cannot override subsequent keyboard navigation. Layout/scroll changes underneath an unmoving pointer do not count as pointer motion.
- Outside the columns, pointer mode falls back to the focused/active directory. Stale depths are discarded. Icons and List continue to use their single active directory.
Ctrl+V while viewing Recent does nothing. After a paste, the destination is shown with the pasted items selected; in Columns, a pasted-into folder opens and keeps focus. While a text field has focus, Ctrl+C, Ctrl+X, Ctrl+V and Ctrl+A act on its text, not on files.
The terminal shortcut, Ctrl+Alt+T, opens in the selected folder whenever exactly one folder is selected, including a folder selected for you on arrival. After Alt+Up from ~/Projects/foo, Ctrl+V pastes into ~/Projects, but Ctrl+Alt+T opens in ~/Projects/foo. Otherwise it uses the same destination column as paste. New Folder remains keyboard-focus scoped. Context-menu paste and drag-and-drop retain their explicit destinations.
Keyboard navigation suppresses stale row-hover effects and pending folder peeks until deliberate pointer input resumes. It does not erase selection or the open folder path.
Focus without selection changes
Pressing blank column content focuses that directory, including an empty one. A plain press there clears file selections in every column immediately and closes the columns to its right; releasing it does not clear them again. When returning to an inactive column, it also selects that column's first visible entry as the range anchor. Presses with Ctrl or Shift held keep the selection until marquee intent is resolved, so a drag can extend it. A plain click on blank space or a disabled control in a preview that is showing something leaves the selection alone; the empty reserved preview slot clears like other empty space. Row clicks, controls, scrollbars, context menus, and marquee selection keep their own interactions. Returning to a column by keyboard preserves a multi-selection; Ctrl+A selects the focused column, not the deepest open column.
Ctrl+click toggles one item in or out of the selection and makes it the range anchor; Shift+click selects every item from the anchor to the clicked item. After a navigation selects the first item, the first Shift+click ranges from that item. Any click re-anchors Shift+Up / Shift+Down, so keyboard extension continues from the clicked item. A Ctrl+click or Shift+click on an item's name or icon moves the keyboard cursor to that item, so the preview follows it.
Shift+Up / Shift+Down extends the selection from the range anchor by one item, Shift+Page Up / Shift+Page Down by one page; the file chooser leaves Shift+Page Up / Shift+Page Down to GTK. Shift+Down with nothing selected selects only the first item; the next selects two. After Escape clears the selection, the range starts at the cursor. With hidden files off, Ctrl+A in Icons, List and the file chooser leaves hidden items unselected.
Escape closes one thing at a time. An open menu, Properties, a rename or new-item editor, the location editor, a filter, or quick preview closes first. With none of those open, Escape clears the active pane's selection and keeps the keyboard cursor and the directory, so Enter then opens the folder under the cursor. In Columns, Escape clears only the active column; parent selections and open columns stay. Outside 10xer mode, Escape with nothing selected in the active column closes the deepest column.
Copy/cut use the selection in the focused column, never a hovered row. In Columns, Ctrl+C or Ctrl+X with nothing selected in the focused column acts on the folder that column shows. Delete moves the selection to Trash without asking; Shift+Delete opens the permanent-deletion confirmation. Outside 10xer mode, both act on the selection even when focus is outside the file list, such as on a header button. In Trash, Delete also asks to delete permanently. Items inside a trashed folder cannot be deleted from the keyboard. With a Ctrl+F result selected, Delete moves that result to Trash and leaves the hidden directory selection alone. While the filter input or a text field, such as preview text, has focus, Delete and Shift+Delete never delete files. In Columns, Delete or Shift+Delete with nothing selected acts on the focused column's keyboard cursor row. When that column has neither a selection nor a cursor, such as an empty open folder, it acts on the open folder itself. In List and Icons, Delete acts on the selection only. Delete in a location without Trash support, or after a Trash attempt fails because Trash is unsupported, opens the permanent-deletion confirmation with Cancel focused and the reason stated; Shift+Delete is unchanged.
Background selection updates from directory loading must not move keyboard focus to an inactive column.
When the focused item is deleted, in Strata or by another program, focus moves to the next visible item, or to the previous one when none follows, and the preview follows it. In Columns, deleting the focused open folder scrolls the item that takes its place, folder or file, into view and, with Mirror columns selection on, mirrors it as keyboard movement does (see Arrows, the header, and the sidebar); with it off, the item is only revealed. Deleting the last visible item clears focus and selection. Other background changes to an open directory keep the selection and scroll position and never take focus.
Returning to a visited directory
Icons and List remember the selection, range anchor, keyboard cursor, and scroll position of the last 128 directories left in that browser. Every route back to a visited directory restores it after its entries load, including nested parents: Back, Forward, Up, breadcrumbs, and typed paths. Arrow-key navigation continues from the restored row, and Shift+arrows extend from the restored anchor. Entries are matched by location, not their previous row numbers; deleted entries are not selected accidentally. The selection and cursor carry over between Icons and List; the exact scroll position comes back only in the view it was left in (and, for Icons, at the same width), otherwise the cursor is scrolled into view. This is temporary browsing state, not a saved preference. A click, scroll or key press in the file view, a view switch, or a failed load cancels an in-progress restoration. Back, Forward and Up move keyboard focus into the restored listing only when focus was inside the pane being left (its Ctrl+F field included) or nowhere: from a header button or with the sidebar focused, they restore the selection and leave focus where it is. Sidebar places, breadcrumbs and typed paths focus the listing, as on a first visit.
In Columns, Back, Forward, Up and breadcrumbs that return to an ancestor of the current directory select the folder you came from, with the cursor on it, and leave its column closed. When that folder is gone or hidden, the first visible entry is selected instead; hidden files stay hidden. Back to a folder that is not an ancestor selects its first item. Icons and List do the same as Columns for an ancestor when they have no remembered position for it.
A navigation that names a target — a typed file path, a Ctrl+K result opened with
Enter or Alt+Enter, Open file location, or an org.freedesktop.FileManager1
request — selects that target instead of restoring the remembered position.
Refreshing a directory
F5 reloads every open column in Columns, and the active pane in Icons and List. Each pane header's Refresh button (tooltip Refresh (F5)) reloads only that pane. With an Auto-refresh interval set, each tick runs the same reload as F5.
F5, the pane's Refresh button, Auto-refresh, and the rescan after a burst of external changes keep the selection, the keyboard cursor and the keyboard focus in every view: a focused row stays focused, and a focused Ctrl+F field keeps focus and its text. Icons and List also keep the scroll position. When the item under the cursor is gone, the cursor moves, without selecting anything, to the next visible item at its old position, or to the previous visible item when none follows. In Columns, this does not happen in a column whose child column is open: no other item takes the cursor there. When a reload removes an open rename field, F2 renames that row again and Menu or Shift+F10 opens its menu.
A refresh never takes focus from the sidebar, the location entry or a dialog. During a slow reload, typing in the Ctrl+F field does not stop focus returning there; Tab or pointer input does, and Escape that closes the filter sends focus to the listing instead.
Creating files and folders
In Columns, List, and Icons, Ctrl+Shift+N or background menu → New Folder
immediately creates new folder. Background menu → New File immediately
creates an empty new file. If the default name is occupied by any item, creation
tries new folder (1) / new file (1), then (2), and so on without overwriting
anything. The pane filter is cleared and the entire allocated default name is
selected: one Backspace clears it, and typing replaces it.
In Columns, a new folder opens as the child column, replacing any stale child column, and the breadcrumb follows it. A new file closes stale child columns, returns the breadcrumb to the parent, and does not open. In List and Icons, the view stays in the parent folder and selects the new item without opening it.
Item menu → New Folder with Selection (or Ctrl+Alt+N) creates new folder
in the same directory, moves the selected items into it, and names it in place.
With nothing selected Ctrl+Alt+N falls back to a plain new folder. The item
is hidden in Trash, Recent, and while a recursive search is open.
Outside 10xer mode, F2 or Ctrl+R on the focused item opens an inline name editor; with Alt, Shift or Super also held, or as Ctrl+F2, neither starts a rename. While another text field has focus, they go to that field, except that in the pane filter they rename the focused item. F5, not Ctrl+R, refreshes. In the editor, Ctrl+A selects only the field's text, and Ctrl+1, Ctrl+2 and Ctrl+3 stay in the field instead of switching views.
For any file or folder rename, Enter, Tab, clicking outside the field (even empty pane space), or moving keyboard focus away, including switching to another window, commits a valid name. Tab also leaves the listing, or the strip in Columns. Escape keeps the original name. Finishing with an empty or invalid name also keeps the original. Cancelling the initial rename does not delete the new item: it remains under its allocated default name. File contents are preserved. While a name is being edited, F5, Ctrl+K, Ctrl+Shift+K, Ctrl+Alt+T and Ctrl+\ do nothing; finish or cancel the edit first.
Clicking inside the field continues editing. With a long name in a narrow column, End, typing, and the arrow keys keep the caret and the extension in view. Existing files retain extension-aware selection (the stem is selected); folder names containing dots are selected in full.
Names containing / or NUL, ./.., and whitespace-only names (including
Unicode whitespace) are invalid. Valid names are used exactly as typed,
including spaces around a nonblank name, hidden-file prefixes, and Unicode.
While you type, an invalid name puts the field in the error style and sets its
accessible description, with no tooltip: Names cannot contain / for a /,
That name is reserved for . or .., and Enter a name for a
whitespace-only name. An empty field is not styled as an error.
Name conflicts, filesystem-specific limits, and permission errors retain the
original item and report an error. After a rename onto an existing name, Escape on
that error returns focus to the item's row.
Filename patterns while filtering
Use Ctrl+F to filter a pane; in 10xer mode, Ctrl+F pages
down and f filters through the footer prompt instead. With Type to search on
(the default), typing a printable character in a file view opens the filter with
that character as the query, and / opens an empty filter without typing /.
Space still opens quick preview, not the filter. Plain text matches a substring of the filename,
ignoring case. Queries of at least four letters or digits also allow one inserted,
missing, substituted, or adjacent swapped character within a whole filename word.
Words are separated by punctuation or spaces. For example, trahs finds
strata-trash.svg, but trash does not find strata-search.svg. Shorter queries
and queries containing punctuation remain literal. Indexed results rank literal
matches ahead of typo matches; parent paths do not qualify a result.
Add * for a whole-filename pattern without typo tolerance:
*.MOVmatchesclip.MOV, but notclip.MOV.bak.IMG*matches names beginning withIMG.IMG*.MOVcombines a prefix and an extension.*holiday*matches names containingholiday;*matches any name.
Each * stands for zero or more characters. Other punctuation (including ?,
[], and regex syntax) is literal. Patterns match file and folder names, not
parent paths, in Columns, Icons, List, and the file chooser. Hidden-file visibility
and Include subfolders still control the scope;
a wildcard does not enable recursive search. Existing result limits still apply.
Clear the input, or press Escape in the input or on a focused result, to restore
the directory listing with focus on its cursor. Backspace in an empty, focused
filter input also closes the filter. Ctrl+K global fuzzy search is
unchanged.
Results follow the watched folders live: the open folder, and in Columns every open column. A matching file that another program creates or renames there appears within about a second, and a deleted one leaves the results as soon as the listing drops it. With Include subfolders on, changes in folders below those reach the results on F5, Auto-refresh, the rescan after a burst of external changes, or when the filter is cleared and opened again. When another program renames the open folder itself, the view follows it and a filter typed in that folder ends, while filters and Ctrl+K searches rooted above it follow the rename. When the open folder is deleted or moved into another folder, the view returns to its nearest parent that still exists, or reloads the folder if it already exists again; either way the filter ends. Neither adds a history entry.
Preview while filtering
In the browser and file chooser, Down from the Ctrl+F input focuses the selected result, or the first result if none is selected. Up/Down then navigate the results; Up from the first result returns to the input without clearing the query. Ctrl+F also returns to the input. With no matches, Down leaves focus in the input. Enter on a focused result opens it, whatever the click-count and preview preferences. Shift+arrows and Ctrl+A select results. Ctrl+C and Ctrl+X act on the selected results at their real locations. When the selected result disappears from the results, the next result, or the last remaining one, is selected. In List and Icons, Tab from a focused result leaves the results in one press, and Shift+Tab then returns to the result that held the cursor. In Columns, moving focus out of the filtered column closes its filter, while focus in its own results, a popover or a dialog keeps it; opening a filter in one column closes and clears any other column's filter.
Menu / Shift+F10 on a focused result opens its file menu. While the input itself is focused, its text-editing menu remains available. Space toggles quick preview for a selected file result in Columns, Icons, and List, including after returning to the query. Previewing a file keeps the query, selection, and current directory intact; on a selected folder result, Space navigates into the folder instead.
While the input is focused, Space types into the query if no result is selected. Shift+Space inserts a space there even with a result selected. Space opens a selected folder in every view without opening or loading the preview pane; unsupported files do not open a preview.
With a result focused, the first Escape dismisses the filter even while its quick preview is open; a second Escape closes the preview. Ctrl+1, Ctrl+2 and Ctrl+3 keep focus in the filter: in the input with the caret after the query, or on the focused result. When you switch views with a query typed and focus elsewhere, for example from the View menu, the results take focus once they show. Loading or refreshing the folder never moves focus out of the input or its results. Neither does another program changing the folder, and that also holds for the 10xer f and s prompts.
Navigating an archive preview
Quick preview (Space, or the item menu's Quick preview) on a local ZIP, 7z, TAR, or TAR.GZ/TGZ opens the archive's member tree instead of extracting it. In Columns (Ctrl+1), automatically previewing an archive shows its contents on the right without selecting a member or taking keyboard focus. Up/Down continue through the current column. Right, Enter, or Space explicitly enter the archive preview and highlight its first member. Enter opens the preview even when automatic previews are disabled; double-click and the archive's context menu still offer extraction. In Icons and List, Enter retains its archive extraction behavior.
Other archive previews start at the archive root with the first member highlighted. In List and Columns modes, arrow keys act on the focused pane, not merely on an open preview. From the listing, Right enters the open preview. While the preview owns focus, its header shows the accent top border instead of the Miller column. Returning to the listing restores its cursor and column header indicator without changing the listing's selection.
Inside the preview, Up/Down move the highlight, Right/Enter opens the highlighted folder, and Left returns to the parent. With Type to search off, or in 10xer mode, k/j, l and h do the same. Keyboard movement never reaches the preview's Close button or F1, and only the current member is outlined. A single click highlights a member and opens a folder; hovering never changes the highlight or the keyboard cursor. Left at the archive root returns focus to the listing without closing the preview. Up/Down then move through listing items; Right enters the preview again. In Columns mode, another Left from the listing moves to the parent column. Right/Enter on a member file does nothing. Navigating never extracts anything or touches the filesystem; Space and Escape still close the preview, which leaves the archive selected in the listing. In Columns, Escape from inside an entered archive preview closes it and returns focus to the archive in its column. In 10xer mode, h at the archive root returns to the listing, Space is swallowed, and Shift+Tab / Escape return or close.
Media preview keys
In the default map, while focus is not in the sidebar, the top bar or a text field, Ctrl+Alt+Space plays or pauses, Ctrl+Alt+Left / Ctrl+Alt+Right seek 5 s, Ctrl+Alt+Up / Ctrl+Alt+Down change the volume by 0.1, Ctrl+Alt+M mutes, and Ctrl+Alt+< / Ctrl+Alt+> step to the previous or next file of the open preview's kind: from a video to the adjacent video, skipping audio files, and from an audio file to the adjacent audio file, skipping videos. In 10xer mode, < and > do the same.
Audio and video previews show a timeline; Tab or a click focuses it. While it has focus, Left/Right seek 5 s, and Shift+Left / Shift+Right or Page Down / Page Up seek 30 s. Home or 0 returns to the start; End or G jumps to the last frame, since seeking to the very end would stop playback. + / = and −, including the keypad's, change the volume by 0.1; reaching zero mutes and keeps the volume to restore. Unlike Left/Right, the paging, jump and volume keys have no Ctrl+Alt form. The volume slider steps 0.1 with the arrow keys and 0.2 with Page Up/Page Down; Home mutes and End sets full volume. Key steps snap to the 0.1 grid, so repeated Down reaches zero and mutes; a drag sets any volume. Other playable files show a seek slider instead of a timeline: the arrow keys step 5 s, Page Up/Page Down 30 s, and Home/End jump to the start and the last frame. Keys and the mouse wheel seek at once; a drag seeks when released. In 10xer mode, whenever the media preview owns the keys, Space plays or pauses, m mutes or unmutes, Up/Down change the volume, < and > step to the adjacent file of the same kind and keep playing, and the timeline keys above also work.
Shortcut footer
Every mode has a compact footer with an F1 Shortcuts button on the left and clipboard status and the item count on the right. The button toggles the reference and shows as pressed while it is open. Settings → General → BROWSING → Show F1 Shortcuts button controls the button's visibility (on by default). The preference is saved and updates all open windows immediately. Item counts and clipboard status remain visible when the button is hidden. With the button hidden and no other footer status to show, such as a count, the clipboard badge, or the 10X tag in 10xer mode, the whole footer hides. F1 opens the Keyboard shortcuts panel centered over the dimmed, blurred window; focus cannot leave it until it closes. F1 always opens the complete, mode-specific reference; closing it restores the button's configured visibility. F1, Escape, or a click outside it closes the reference, which blocks file-operation shortcuts while open. It stays open when the window loses focus. The reference is the only complete in-app keybinding list; it shows only the currently active map and live-updates when 10xer mode changes. In 10xer mode, a pending chord's footer panel also lists the keys that can follow it.
The reference opens with focus in Search actions or keys…, scrolled to the top. Typing keeps the rows whose keys, key context or action contain the text, ignoring case. Translated text matches, and key names match in English and in the interface language: under German, strg+c and ctrl+c both find Copy. Each alternative in a row also matches spelled out in full, so ctrl+0 finds the Ctrl++ / − / 0 text-size row. A typed - matches the − in labels and the – of digit ranges, so 1-9 finds Ctrl+Shift+1–9 / 0. A query with no match shows No matching shortcuts. The category list shows All and each section with its row count; choosing one shows only that section. In windows narrower than 1480 px, the header stacks, categories become wrapping pills without counts, and results use one column. In the default map the sections are the current view's navigation (Columns, Icons or List), then Files and selection, Search and tools, and Preview media. In 10xer mode the reference adds Places, Preview and a 10xer mode section for keys the default map lacks. Reopening the reference keeps the previous search text and category. In the search field, typing, Delete, Ctrl+A, Ctrl+C, Ctrl+V and Ctrl+X edit the query, and Up, Down, Page Up and Page Down scroll the results without moving focus, Ctrl+Z undoes the last query edit, and Ctrl+Y or Ctrl+Shift+Z redoes it. Tab and Shift+Tab cycle the search field, the selected category and the results. Ctrl+B jumps to the categories, Ctrl+F to the search field and Ctrl+L to the results. In the categories, arrows or h/j/k/l select the previous or next category, and Home and End the first or last. In the results, arrows, j/k, Page Up/Page Down and Home/End scroll the list. A line at the bottom summarizes these keys: Ctrl+B categories · Ctrl+F search · Ctrl+L list · j / k / ↑ / ↓ move · Tab cycle · Escape close. In 10xer mode ~ also toggles the reference; in the default map it does not. While a 10xer footer prompt has focus, ~ types into the prompt instead, and F1 still opens the reference. With the Russian layout active and a text field focused, Shift and the ё key type Ё rather than toggling the reference. F1 with Ctrl, Alt, Shift or Super held does not toggle the reference, and while it is open Ctrl+1, Ctrl+2 and Ctrl+3 do nothing. Closing it returns focus to the control that had it before.
10xer mode
Settings → General → BROWSING → 10xer mode (off by default, toggle with Ctrl+Shift+M) hides window Search and pane Close/filter/refresh/sort chrome and installs Yazi-style keys. Ctrl+Shift+M is the only key that leaves the mode. While the mode is on, the footer shows 10X in its far right corner, after the item count. 10xer's typed commands (f, s, / and the other prompts) use the footer prompt, never the pane filter revealer. Ctrl+K still opens global search. See 10xer mode for the keymap.
Ctrl+Shift+M also works while a browser text field has focus. Modal dialogs retain their own input handling. Leaving 10xer mode clears retained footer filters/search and forced recursion in all windows, so default Ctrl+F obeys Include subfolders again. It ends visual/preview keyboard ownership without clearing the ordinary listing's fill or closing the preview. Escape dismisses one interaction at a time, including an open preview; recursive results have a separate order described in Escape precedence.
The F1 / ~ reference panel lists the active map and live-updates when the mode
changes. Its navigation section is specific to the current view, and in the
portal file chooser it lists only the keys that request allows.
Context-menu hints use x, y, p, d / D, r, i, and M / C / R
(Move to, Copy to, Restore). i toggles a file's preview without taking focus, or is the next column or folder peek for a directory.
Rename shows r instead of F2 / Ctrl+R. Copy path, Duplicate, Pin to sidebar,
Open in Terminal, and Quick preview in the file chooser show no hint. Other rows
keep their default-map hints, such as Enter beside Open. In the default map, the
y (copy path) and p (pin) hints show only while Type to search is off,
because type-to-search claims those letters otherwise.
While a pane shows its search-results page (including filtered results), the footer
shows the displayed result total in both default and 10xer mode, including
0 items on a miss.
Selecting results does not replace that total with the hidden directory's selection;
its accessible description gives the result file/folder breakdown. Dismissing results restores the
ordinary directory count or selection summary. Until the search for a typed query
reports back, the footer keeps describing the directory. The filter: / search:
mark and the hit path at the footer's left end show only in 10xer mode, which
hides the pane's filter input; the default map shows the total alone.
With no selection in the ordinary listing, the footer shows the directory's item count, such as 12 items; its accessible description gives the file and folder breakdown. Selections show a folder/file breakdown, such as 1 folder, 2 files selected (64 MB). Selecting every item shows the breakdown without a size, and selecting more than 64 items, but not all, shows N items selected without a size. Sizes sum available metadata for selected files only; folder contents are not scanned or included. Missing file sizes are marked incomplete or unavailable.
After copying or cutting files, a highlighted Files on clipboard pill appears to the left of the item count. Its accessible description reads Press Ctrl+V to paste into a supported directory. It reflects the file clipboard, including compatible copies from other applications, rather than assuming every clipboard contains files. It stays available after copying/pasting, and disappears when a completed cut consumes the clipboard or it is cleared/replaced with text. The clipboard status and paste shortcut remain available when the F1 Shortcuts button is hidden. Copied listing items show the Lucide copy icon in place of their thumbnail; cut items keep scissors, which wins if both would apply. Clearing the clipboard or unyank removes the copy overlay.
The hints describe file-view controls; text fields, dialogs, and media previews retain their own keyboard behavior. Mode changes update both the footer and the reference immediately. Closing keyboard-opened help restores the previous focus.
Arrows, the header, and the sidebar
In Icons and List, plain arrows move interface focus rather than changing directories:
| Key | Icons | List |
|---|---|---|
| Left | Move one tile left; at the left edge, focus the visible sidebar | Focus the visible sidebar |
| Right | Move one tile right | Stay in the file list; on a file, enter an open preview |
| Up / Down | Move by visual rows | Move through file rows |
| Enter | Open the current item | Open the current item |
In both views, Up and Down also select the item they land on, replacing the selection. They never open it, even when single-click opening is on.
Enter on a previewed video, from the listing or inside the preview, pauses the preview and asks the default player to start where it stopped. mpv, VLC, Celluloid and MPlayer take the position on their command line; other players open the file from the beginning, as does a position inside the first or last second.
Up from the first Icons row or first List item focuses the navigation header, including in empty directories, where the pane itself holds focus. Left/Right traverse its enabled controls without triggering navigation; Enter/Space activates a control. Down returns to the item you left without changing selection. Left from the header's first control can reach the visible sidebar.
In Columns, Up from a column's first item focuses that column's header controls, and Down returns to its list. Left from a column's first header control, or Right from its last, moves into the neighboring column's header. Left in the first column focuses the visible sidebar on the row for the current place.
From the sidebar, Right returns to the item you left (or the current file view if navigation replaced it, or if you entered the sidebar from the header rather than from a file). Up/Down move between places. Up from the first sidebar row (Home by default) continues into the top navigation bar instead of stopping. Left/Right traverse its enabled controls without activating them; Down returns to the sidebar row you left. If the sidebar is hidden from the top bar, Down returns to the files instead. Empty file views also support these round trips. If the sidebar is hidden, Left in the file view does not change directories.
In the default map, Ctrl+B shows or hides the sidebar. Ctrl+Shift+B shows a hidden sidebar and focuses the row for the current place; pressing it again in the sidebar returns focus to where it was. Outside 10xer mode, Enter on a sidebar row opens the place with its first item selected; a click opens it with nothing selected. In Icons and List, a folder you left recently restores its remembered position instead.
In the default map each file listing is one Tab stop; arrows move inside it. Tab from the listing goes to the next interface control (the open preview's controls, then F1 Shortcuts), and Shift+Tab goes back through the List sort headings, an open filter and the pane header actions, then the sidebar. Tab or Shift+Tab into a listing lands on the keyboard cursor, so Enter, Space and Ctrl+C act on the item that shows focus. In Columns the whole strip is one stop: Tab into it lands on the active column's cursor without changing the active column, Tab from any column leaves the strip, and Shift+Tab reaches the active column's open filter, then its header actions, then the control before the strip.
Screen readers announce each item by its name, described as Folder, File, Folder link, File link, Broken link or Other. Each pane is a group named after its directory and described as Columns view, Icons view or List view, and the item list inside it is named after the directory and described as Files. Pressing Tab repeatedly from the window's first control reaches the listing. Menu items are named after their action and carry their shortcut in their description, not their name. Selecting an item sets the selected state on that item and on no other. With default preferences, the header buttons are named Search (Ctrl+K), Appearance, Settings, Close window and Toggle sidebar (Ctrl+B). Modal dialogs have the dialog role and are named after their title. Item kind, view and list descriptions are in the interface language, and shortcuts in accessible names and descriptions use its key names, such as Strg in German. An icon-only button shows a tooltip, such as Search (Ctrl+K); labelled buttons, menu items, file rows and breadcrumbs show none. A sidebar place's or breadcrumb's full path is its accessible description, not a tooltip.
An empty, unreadable or still-loading directory has no rows to focus, so the pane itself takes focus. It draws the accent focus ring, is named after the directory, and is described by what it shows ("This directory is empty", the error, or "Loading"). Tab and Shift+Tab leave it as they leave a listing, and Shift+Tab from the footer returns to it. In Columns, an unreadable directory's Retry button is the next Tab stop inside it. When the entries appear, focus moves back to the keyboard cursor.
Settings → General → BROWSING → Keep arrows in file list (off by default) stops arrow keys from leaving the file list. Tab, Ctrl+Shift+B and the pointer still reach the header, sidebar and top bar. Ctrl+\ toggles it live and updates the Settings switch. The file chooser respects the same preference. In 10xer mode the preference is not used, its Settings row reads Not used in 10xer mode., and Ctrl+\ does nothing.
Alt+Left / Alt+Right / Alt+Up remain Back / Forward / Parent in every mode, and Alt+Home goes to your home folder. Home or Ctrl+Up and End or Ctrl+Down jump to the first and last item, Page Up/Page Down move a page, Shift+Home and Shift+End extend the selection to either end, and, in the default map, Ctrl+Space toggles the focused item's selection. In the default map, Columns keeps Miller-column navigation: Right enters folders or moves into an existing pane to the right. In List, Right stays on the current row. On a focused file, Right never opens the file. On a local ZIP, 7z, TAR or TAR.GZ in Columns, Right, Enter and Space enter the archive preview. In List or Columns with a preview open, Right moves focus into that preview; otherwise it does nothing. Enter opens other files. Opening a folder with Enter selects its first item; opening it with the pointer selects nothing. In Icons and List, a folder you left recently restores its remembered position instead. With Type to search off, h / j / k / l act as the arrow keys in every view and in the file chooser. Backspace in List and Icons opens the parent folder. In Columns it closes the focused nested column and those after it; from the first column it opens the parent folder with the folder you left selected. Ctrl+1, Ctrl+2 and Ctrl+3 switch to Columns, Icons and List, even while typing in the filter, keeping the directory, the selection, the focused item and the sort. In 10xer mode, arrows stay in the Columns, List, and Icons panes. Tab moves from the file list to the window header, where Enter / Space activate the focused control and h / j return to the files. Ctrl+Shift+B focuses a visible sidebar; a hidden sidebar stays hidden until Ctrl+N or the header toggle shows it. In the sidebar, j / k and Up / Down move between places and device controls, l / Enter / Space activate the focused one, and h / Left / Backspace return to the files without changing the selection. A Tab or arrow key from the footer still returns to the file list. List and Columns l / Right open a directory or enter a file's preview when possible. Icons h / j / k / l and arrows always move to the next icon in that direction, including across search-result icons; they never preview or change location. On a file, i toggles the preview without moving focus. On a directory it opens the next Miller column without focusing it, or toggles the folder-peek popover in List and Icons.
Columns reserves preview space from startup, even before a file is previewed. Space, i, and the preview's close button dismiss the content without reclaiming that space, so opening or closing a preview does not move the columns under the pointer. Switch Appearance → Preview panel off to explicitly reclaim it. This reservation is window-local and does not enable automatic previews on its own. In Columns the preview fills the space right of the focused column, at least 300 px. When less than 240 px would remain beside the focused column, the preview content hides and media pauses, but the reserved slot keeps the remaining width beside the focused column, down to zero. Dragging the divider sets a width of at least 300 px that lasts until the window closes; in Columns the preview still fills wider free space and yields to columns only down to that width. F8 focuses the divider, and the arrow keys then move it; moving it with the keyboard sets the same manual width as dragging and draws no outline. See Previews for the panel itself.
Space on a focused supported file opens quick preview, and a second Space closes it; Space on an unsupported file opens nothing, and Space on a selected folder enters it without opening the preview. With the preview open, moving the cursor, or extending the selection with Shift+arrows, shows the newly focused file. In List, moving onto a folder or a file with no preview hides the preview; in Icons the panel stays and shows No preview for this selection. Moving onto a supported file again shows it. With the caret in preview text, Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X, Ctrl+D and Delete act on the text, not on files.
In Columns, the pane to the right mirrors keyboard selection like Finder: moving with Up/Down, Page Up/Page Down, Home/End or Ctrl+Up / Ctrl+Down onto a folder shows its contents in a child column that takes the reserved preview space, onto a previewable file closes that child column and, when Single-click file previews is on, opens quick preview in the same space, and onto any other file closes the child pane. The focused column stays where it is throughout. When keyboard movement focuses a column that is clipped at all, even by a few pixels, the strip scrolls until the column is fully visible; a fully visible column stays in place. A column wider than the strip stays put while it fills the strip; otherwise the strip scrolls to its left edge. Mirroring waits 75 ms after the last key, so holding Down loads only the folder where the cursor stops. Shift-extended ranges do not mirror, and neither does a column whose filter has a query typed in it. In a column with no keyboard cursor yet, Home or Ctrl+Up lands on the first item and End or Ctrl+Down on the last. A preview closed with Space, i, Escape, the close button, or Appearance → Preview panel stays closed while mirroring until it is opened explicitly again. Pointer selection keeps the configured click behavior. Clicking a folder whose column is already open focuses that column rather than closing it, and a double-click ends exactly where a single-click open does; a slow click on a selected folder's name still renames it. In every view, a plain click on an item that is part of a multi-selection collapses the selection to that item and then applies its single-click behavior: a folder set to open on one click opens (in Columns, as its child column), and a previewable file is previewed when Single-click file previews is on. Pressing a member and dragging still drags the whole selection. Settings → General → BROWSING → Mirror columns selection (on by default) toggles the mirroring. 10xer mode follows the same preference for its cursor in Columns; see 10xer mode. l / Right enters a directory or a file preview, and i toggles a file's preview or opens the next column / toggles folder peek for a directory.
Closing dialogs and overlays
Closing an overlay or dialog by any route (Escape, its close or Cancel button, or a click outside it) returns keyboard focus to the control that opened it. This covers Ctrl+K search, Ctrl+Shift+K folder jump, Compress, archive conflicts, Customize, and error dialogs. If that control is gone, for example after the view was rebuilt or an inline editor closed, focus goes to the file list cursor, or to the pane of an empty or loading folder. File-operation progress always returns focus to the file list cursor, because the operation changes the listing. Choosing a search result hands focus to the browser instead, and a result the browser selects while a dialog closes, such as an extracted folder, keeps focus.
Closing a dialog over a modal that stays open, such as the action editor over Settings, returns focus to its opener inside that modal. When that opener is gone, for example an action row the dialog re-rendered, focus goes to the first focusable control in the remaining modal. A dialog closed from the keyboard keeps the focus ring on the control that receives focus, both over a modal that stays open and once the last modal closes. The exception is a dialog closed from the keyboard that opens another dialog as it closes: focus lands on the new dialog's default button, which shows no focus ring.
Closing Settings always returns focus to the file list cursor, even when Settings was opened with the gear button. The one exception is a filter field or filter result that had focus when Settings opened, for example with Ctrl+,: it gets focus back.
Customize opens with focus on Done, so one Escape closes it. Closing its custom color dialog returns focus to the custom color button. In the custom color dialog, Escape from the color editor returns to the palette, and Escape from the palette closes the dialog without applying.
Confirmation dialogs open with the confirm button focused, so Enter confirms and Escape cancels: Permanently delete, Empty Trash, Restore, paste and archive Replace, Run, and Forget saved password. The exception is a delete where Trash is unavailable, which opens with Cancel focused. Outside a text field, an arrow key moves focus to the nearest button or control in that direction, and Enter activates the focused button, so Enter with Cancel focused cancels. Enter also toggles a focused checkbox or switch, and Down on a menu button opens its menu. While a popover menu is open, keys go to the menu rather than to browser shortcuts. In the delete confirmation, h also focuses Cancel and l the confirm button. Enter in a single-line text or password field of the Compress, archive password or mount authentication dialog activates the primary button, unless it is disabled; in a multi-line field it inserts a newline. In Settings, Escape in a non-empty search field first clears the query. In Customize, Escape with the emoji picker open closes only the picker.
Focus cannot leave an open dialog: focus that moves outside it returns to the dialog, and a key pressed with focus outside it only moves focus back in. While a dialog is open, browser shortcuts do not act behind it, but Ctrl++, Ctrl+− and Ctrl+0 still change the text size. While a dialog or Settings is open, Ctrl+K, Ctrl+Shift+K, F5, Ctrl+Alt+T and Ctrl+\ do nothing and the dialog keeps focus. Ctrl+K and Ctrl+Shift+K still close the search palette they opened. Once a dialog is animating closed, those five keys act as if no dialog were open; other browser shortcuts still do nothing until it is gone, and the text-size keys still act.
In Ctrl+K search, Up and Down move the highlight while the caret stays in the query, and typing edits the query. The first result starts highlighted, so one Down highlights the second. With an input method composing in the query, an Enter that the input method passes back after committing opens the highlighted result. Enter closes search and opens the highlighted result: a folder opens, and a file is revealed selected in its folder with quick preview open. With Settings → General → SEARCH & FILTERING → Open search results directly on, the file launches instead. Alt+Enter opens its containing folder with the result selected and focused.
Ctrl+Shift+K opens Jump to a folder…, which lists the local folders you have
opened in Strata, most frequently and recently visited first, up to 100. Each
space-separated term may match anywhere in a folder's path, so dev str finds
~/dev/strata, and terms accept the 'exact, ^prefix, suffix$ and !excluded
forms; strata !notes hides folders whose path matches notes. Folders whose names
match more terms rank higher, and an exact name ranks first among them. Arrow keys choose a folder and Enter opens it.
Before any folder is recorded it shows No folder history yet, and a query that
matches nothing shows No matching folders. In 10xer mode Ctrl+Shift+K does
nothing; z and Z jump to visited folders instead (see
10xer mode).
Opening and navigating the context menu
Menu (the hardware context-menu key) and Shift+F10 open the selection-aware context menu without the pointer. With the keyboard cursor on a selected item, the menu opens for that item, or for the whole multi-selection if the item is part of one. With the cursor on an unselected item, or with nothing selected, it opens the pane's background menu. The menu is anchored to the focused item or pane, never to the pointer, and a background menu opened from the keyboard stays inside the window. On a focused Ctrl+F result it opens that result's file menu. With a text field focused, Menu and Shift+F10 open the field's text-editing menu instead. With a sidebar place, Trash or drive row focused, they open that row's menu, with 10xer mode on or off. Ctrl+Shift+F10, Shift+Menu and Ctrl+Menu open no menu. Alt+Enter with one item selected opens Properties for the focused item. A keyboard-opened item menu is anchored to the item's right edge in Columns and Icons, and to its center in List.
Each action with a shortcut shows it at the right of its row, such as Ctrl+C beside Copy, Enter beside Open, F2 / Ctrl+R beside Rename and Alt+Enter beside Properties, with key names in the interface language: German shows Strg+C beside Copy and Entf beside Move to Trash.
Right-clicking an item also makes it the keyboard cursor, without opening it. An already-selected item keeps the existing multi-selection; an unselected item becomes the only selected item. Escape returns keyboard focus to that clicked item.
A menu opens with keyboard focus on its first visible action, and focus stays there while Open With entries load, even with the pointer resting over the menu. Ctrl+A leaves an open menu open. Once open: Up/Down move between enabled actions, wrapping past the first/last; Home/End jump to the first/last enabled action; separators and disabled actions are skipped. Enter/Space activates the focused action immediately on key press. On a submenu row such as Actions or Send to…, Right, Space or Enter opens the submenu with its first action focused, and Left closes only the submenu and refocuses its row. In the file chooser's menus, Tab and Shift+Tab also move between enabled actions. Escape closes the menu without changing the selection and returns keyboard focus to the item or pane that opened it. This applies in Columns, Icons, List, Trash, and the file chooser. Closing Properties follows the overlay rule; choosing Rename hands focus to the editor instead.
10xer mode reference
10xer mode is an opt-in Yazi-style browsing map. In Settings → General → BROWSING the row is titled 10xer mode and its subtitle is Opinionated keyboard-centric mode with Yazi-style navigation. Disables some features. Toggle with Ctrl+Shift+M. The footer shows a compact 10X pill in its far right corner, after the item count, while the mode is on. It hides window Search, the pane Close, filter, refresh, and sort controls, and the List and Icons pane header (back, forward, and up buttons with the folder title) in interactive browsers, disables type-to-search, and uses the footer as the typed-command surface. The window's own close button and the clickable List column headings stay. The portal file chooser follows the same preference: it hides the same pane chrome, uses this keymap and the footer prompt, and keeps Accept, Cancel, and the header close control. Enter / o confirm a file. Escape is the way out: it cancels the dialog after dismissing a prompt, filter, or preview. The chooser continues to disallow folder peeking and column mirroring, so i does not open a peek or an extra Miller column there.
Turn it on in Settings → General → BROWSING → 10xer mode, or with Ctrl+Shift+M. The choice is saved and live-updates every window. F1 or ~ opens the in-app table of commands that currently run; it is the only in-app keybinding reference. While the mode is on, the reference lists only the 10xer map, in these sections: the current view's navigation (such as Columns navigation), File chooser (in the file chooser only), Places, Files and selection, Preview, 10xer mode (the keys the default map lacks), Search and tools, and Preview media. Turning the mode on or off, in any window, switches an open reference to the newly active map. While the mode is on, the Settings row shows (experimental feature, under active development) under its subtitle. The footer shows only the 10X pill; the experimental note is in its accessible name and description.
Paste destinations, cursor versus filled selection, and pointer ownership stay as in keyboard navigation.
The keys work on every keyboard layout. On Russian and other non-Latin layouts a letter key acts as the Latin letter it carries, so the key that types о is j. Digits count by their position on the top row, and Caps Lock never changes a command. On a German layout, ö in the file list arms the ; chord, as ; does. See keyboard layouts for the full rules.
Enter and leave
| Key | Action |
|---|---|
| Ctrl+Shift+M | Toggle 10xer mode. The only key that leaves the mode. |
| Q | Close the current window through the normal close path, so a running custom-action job still blocks closing the last window. Lowercase q does nothing. |
| F1 / ~ | Show or hide the in-app shortcut reference |
| Ctrl+, | Open Settings, canceling any armed chord |
Ctrl+Shift+M also works while a browser text field has focus; modal dialogs keep their own input handling. With the Russian layout active and a text field focused, Shift and the ё key type Ё rather than toggling the reference.
Turning the mode on in an open window shows a centered 10xer splash for about 1.5 seconds. It takes no focus or clicks, and with reduced motion it appears without animation. A saved choice applies at launch in every window, before Settings opens, and launching with the mode already saved shows no splash. The footer keeps its height when the 10X pill appears.
Turning the mode on hides an open pane filter bar and re-runs its query with f matching. Turning the mode off shows the bar again and re-runs the query with default matching.
Type to search, Keep arrows in file list, and Include subfolders stay saved and editable. While the mode is on they are unused, and those Settings rows show Not used in 10xer mode. Mirror columns selection stays in effect and drives the Columns cursor.
Leaving the mode clears footer prompts (including typed credentials), chords, find highlights, retained filters/search results, a keyboard folder peek, and preview keyboard ownership in every open browser window. It leaves the ordinary listing's filled selection, any Miller column already opened, and any open preview intact. Default Ctrl+F again follows the saved Include subfolders preference; a previous s search does not force it to recurse.
Navigation
Arrows stay in the file list. In List and Columns, h is parent, never the sidebar. In Icons, h / j / k / l and arrows move among tiles.
| Key | Action |
|---|---|
| h / Left | List and Columns: leave the preview, or parent folder, closing the Miller child pane |
| l / Right | List and Columns: open a directory, or enter a file's preview when possible |
| h / j / k / l / arrows | Icons: move spatially among tiles. Do not enter a folder, leave the folder, or open preview. |
| Enter | Open the focused item, including files |
| j / k / Up / Down | List and Columns: next / previous item in listing order |
| g g / Home | First item |
| G / End | Last item |
| Ctrl+U / Ctrl+D | Half page up / down |
| Ctrl+B / Ctrl+F / Page Up / Page Down | Full page up / down |
| H / L / Alt+Left / Alt+Right | Back / forward in history |
| Backspace / Alt+Up | Parent folder |
| i | On a file: toggle the preview drawer without moving focus into it. On a directory: in Columns, open the next Miller column without moving focus into it (mirroring usually has already); in List and Icons, toggle the folder-peek popover. |
| J / K | Scroll the open preview without taking focus |
| < / > | While the open preview shows audio or video: move to the previous / next file of the same type, still playing if it was playing, without taking focus |
In Columns, the saved Mirror columns selection preference (on by default)
applies to the cursor: shortly after j / k / arrows land on a directory,
its contents open in the next Miller column without moving focus. On a file the
child column closes, and a previewable file opens the preview drawer when
Single-click file previews is also on; focus stays in the listing. With mirroring
off, cursor keys only move the cursor. While a v / V range is active,
mirroring waits, so walking the range never opens or closes a column. In List and Icons, cursor keys never open
a child column or a preview. l / Right enters a directory or a file preview.
In Columns, i on a directory opens the next column and leaves focus where it
is, even with mirroring off. A second press does not move focus. In List and Icons, i toggles
the existing folder-peek popover for the focused directory. That popover is the
directory peek, not the saved Folder peeking switch and not a file preview.
Pressing i again, or Escape, closes the popover. Escape does not close a
Miller column. i on a file opens the preview drawer if it is closed and
closes it if it is open; keys stay in the listing, so j / k keep moving
the cursor and the preview follows it. Use l / Right (List and Columns) or
J / K to read it. An unpreviewable file flashes Nothing to preview. In
an empty folder i does nothing.
In List and Columns, l / Right on a previewable file opens the
preview if it is closed and moves keys into that pane. A further l / Right
stays there and does not open the file. Then j / k / arrows,
g g / Home, G / End, Ctrl+U / Ctrl+D / Ctrl+B / Ctrl+F, and
Page Up / Page Down scroll the document instead of the listing. h / Left
returns to the miller column or folder without closing the preview or going to
the parent; a following h still goes to the parent. Unpreviewable files and
empty folders flash Nothing to preview. Icons have no preview-entry key.
While the preview owns keys, an accent bar runs across the top of its header,
like the Miller column destination bar, and no column shows that bar. The listing
keeps its fill and location, and its cursor returns with the keys. Leaving the mode, clicking the listing, or
closing the drawer releases ownership; ownership never outlives the drawer.
Preview keyboard ownership
Each preview surface owns a fixed set of keys (below). It also swallows the listing's motion and selection keys (j / k, arrows, paging, Space, v / V, Ctrl+A, Ctrl+R), so they never move or fill the listing behind the drawer.
Listing commands no surface uses hand the keys back to the listing, with the drawer still open, and run there on the previewed item:
- Folders: Backspace, H / L, Alt+Left / Alt+Right / Alt+Up, g places
and g + / g −, z / Z. In a document or archive g g still goes to the top, and
every other valid g step runs from the listing; an unknown second key
flashes
Unknown chordand leaves the keys in the preview. - Prompts: / (except in a searchable document, where it opens find), ?, n / N, f, s.
- Files: o / Enter (except where the surface uses Enter), y, x, p / P, Y / X, d / D / Delete, a, r / F2, c, ,, ., ;, O, M / C, R, Ctrl+C / Ctrl+X / Ctrl+V (a document or archive tree keeps Ctrl+C), Ctrl+Shift+N, Alt+Enter, and Menu / Shift+F10.
Window commands (Q, F1, ~, F5, Ctrl+K, Ctrl+L, Ctrl+,, Ctrl+1 / Ctrl+2 / Ctrl+3, Ctrl+H, Ctrl+N, Ctrl+Shift+B, Ctrl+Shift+M, undo / redo, text size, and the Ctrl tab shortcuts) work without moving the keys. The exception is a text or source preview shown in SourceView rather than in recycled rows (see limits and fallback): while it has the keys, Ctrl+1 / Ctrl+2 / Ctrl+3 and undo / redo do nothing. Return the keys to the listing first, for example with Shift+Tab. Any other key is swallowed. Inside a text field, F1, Ctrl+Shift+M, Escape, Shift+Tab, F5, Ctrl+K, Ctrl+,, the Ctrl tab shortcuts, and text size still work; every other key is typed or edits the text.
| Key | Document | Archive tree | Password field | Media |
|---|---|---|---|---|
| j / k / Up / Down | Scroll | Move the member highlight | Typed / text editing | Up / Down volume; j / k swallowed |
| h / Left | Return to the listing | Archive parent; at the archive root, return to the listing | Typed / caret | h returns to the listing; Left seeks −5 s, Shift+Left −30 s |
| l / Right | Swallowed | Open the highlighted folder; a member file does nothing | Typed / caret | Right seeks +5 s, Shift+Right +30 s; l swallowed |
| Enter | Open the file from the listing | Same as l | Unlock | Open the file from the listing. A video opens in the default player; mpv, VLC, Celluloid, and MPlayer start where the preview stopped. |
| Space | Swallowed | Swallowed | Typed | Play / pause |
| i | Close the drawer | Close the drawer | Typed | Close the drawer |
| Home / G / End | Top / bottom | First / last member | Caret (G typed) | Seek to the start / the last frame |
| Paging keys | Scroll half / full page | Swallowed | Text editing | Page Up / Page Down seek +30 / −30 s; Ctrl+U / Ctrl+D / Ctrl+B / Ctrl+F swallowed |
| / | Find in the document; see document previews | Listing find prompt, as / from the listing | Typed | Listing find prompt, as / from the listing |
| 0 | Swallowed | Swallowed | Typed | Seek to the start |
| + / = / − | Swallowed | Swallowed | Typed | Volume up / down |
| m | Swallowed | Swallowed | Typed | Mute / unmute |
| < / > | Swallowed | Swallowed | Typed | Previous / next file of the same type in the listing; playback continues if it was playing |
| J / K | Scroll | Scroll | Typed | Swallowed |
| Shift+Tab | Return to the listing | Return to the listing | Return to the listing | Return to the listing |
| Escape | Close find if it is open, otherwise close the drawer | Close the drawer | Close the drawer | Close the drawer |
Returning to the listing keeps the drawer open and lands on the same cursor. Closing with Escape or i also returns the keys to the listing, so the Miller column regains its destination bar. i therefore toggles the preview from either side: open from the listing, closed from the preview. A focused media timeline takes the Media keys above. A focused preview button or slider (reached with Tab or the pointer) keeps GTK's own Space / Enter / arrow handling; Shift+Tab and Escape still return or close. The volume slider steps 0.1 with the arrows and 0.2 with Page Up / Page Down; Home mutes and End sets full volume. Browsing archive members never extracts them, opens a listing file, or changes the listing's cursor or fill. Unlocking a password-protected archive hands the keys to its member tree. Ctrl+A / Ctrl+C select all and copy the document's text, never listing items; with l the keys go to the document itself (text, source, or PDF) once it has rendered. In a document, Shift+Left / Shift+Right / Shift+Up / Shift+Down, Shift+Home, and Shift+End select text instead of scrolling, and Ctrl+Home / Ctrl+End move the text caret to the start / end of the document. Keypad / opens find like /. The find button's tooltip reads Find in preview (/) while the mode is on and Find in preview (Ctrl+F) while it is off; toggling the mode updates the tooltip of a preview that is already open. In media, keypad + / − also step the volume.
A password prompt takes focus as soon as it appears, including when i or cursor movement shows a locked archive. It then owns the keys like any other surface: the header shows the owner bar, the Miller column drops its bar, and i, h, j, k, and l are typed into the password until Escape, Shift+Tab, or unlocking moves focus. If the drawer is hidden for lack of room when l is pressed, it takes the keys when it reappears for the same file; moving the cursor first cancels that.
With 10xer mode off the default map is unchanged: an archive tree keeps its arrow, k / j / h / l, Enter, Space, and Escape keys described in keyboard navigation, and media keys stay on Ctrl+Alt.
In Icons, h / j / k / l and arrows (including keypad) always move to the next icon in that direction, including while the icons on screen are search results. They stay in the current folder. They never open the preview drawer, dismiss search, or transfer keyboard ownership into a preview. Enter / o still open the focused item. Backspace / Alt+Up still go to the parent.
g g is first item. g h is Home. In Columns, g g and G in a column with no cursor land on its first and last entry.
Selection
Space toggles the keyboard cursor, not pointer hover, and does not preview. i toggles a file's preview without moving focus; in List and Columns, l / Right enter it. On a directory i opens a column or toggles folder peek.
| Key | Action |
|---|---|
| Space | Toggle the focused item and move down |
| v / V | Visual select / visual unset |
| Ctrl+A | Select all in the focused pane |
| Ctrl+R | Invert the selection |
| Escape | Dismiss the current interaction, one step per press; see the precedence below |
On a cursor-only row, Space adds that item and moves down; it does not deselect it. After Space, Ctrl+A, Ctrl+R, or leaving visual, j / k / g g / G / paging move the cursor without rewriting the fill. v then motion starts a new range from the cursor. V subtracts the walked span. In visual mode, Space toggles the cursor item without moving it.
A range walks the pane in displayed order, including List type groups, and only
rewrites the fill of that pane. Walking back toward the anchor restores the items
the range had covered; items toggled with Space stay toggled. The footer shows
VISUAL or UNSET while a range is active. Pressing the same key again or
Escape leaves visual mode and keeps the fill; the other key starts a new range
at the cursor. Opening another folder, moving to another pane, changing the view,
a pointer selection, Ctrl+A, Ctrl+R, or leaving 10xer mode also end the
range. In an empty folder v / V, Space, Ctrl+A, and Ctrl+R
flash Nothing to select.
v / V are the only way to select a range. Shift+arrow keys and Shift+Page Up / Shift+Page Down do nothing in the listing; to select while paging, start a range and use Page Up / Page Down or Ctrl+D / Ctrl+U / Ctrl+F / Ctrl+B, which extend it like j / k.
Escape precedence
Dialogs, the shortcut reference, text editors, and an open folder-peek popover handle Escape before browsing; active autoscroll also stops before listing dismissal. Closing the peek does not close a Miller column. In a footer prompt it cancels that prompt: f clears its filter, / / ? clear find highlights, and a nonempty s keeps its results. An armed chord is canceled before any listing action.
With no prompt or chord, each press takes the first applicable step:
- Recursive
sresults: leave visual mode (keep the fill), dismiss find highlights, close an open preview, then dismiss the results. Dismissal restores an earlier committed f filter if one existed; otherwise it restores the directory listing. - Ordinary listing or
fresults: leave visual mode over thefresults (keep the fill), dismiss the hidden filter, dismiss find highlights, leave visual mode (keep the fill), close an open preview, then clear the selection. A fill made on thefresults goes away with them.
While the preview owns keys, Escape closes an open find bar, then the drawer, before any other step, and closing the drawer returns keys to the listing. Unlike h while the preview owns keys, the preview-close step actually closes the drawer. Leaving visual mode or closing a preview can therefore require an extra Escape before retained search results disappear. Once nothing is left to dismiss, Escape does nothing: it never closes a Miller column or the window. The sidebar and header controls take the same steps; clearing a filter or closing the preview from there returns focus to the file list.
Tabs
From the listing, press t, then a second key. The footer shows t- and its available commands. Escape cancels the chord; text fields, menus, and file-chooser requests do not arm it.
| Chord | Action |
|---|---|
| t n | Open a new tab at the current location |
| t x | Close the active tab (the last tab closes the window) |
| t t | Select the previous tab in strip order, wrapping from first to last |
| t 1–9 | Select tabs 1–9 in their current order |
| t 0 | Select tab 10 |
The digit step also accepts Shift with the digit.
The shared Ctrl-based tab shortcuts also remain available: Ctrl+T creates a tab, Ctrl+W closes it, Ctrl+Tab / Ctrl+Shift+Tab cycle tabs, and Ctrl+Page Up / Ctrl+Page Down select the previous / next tab, wrapping at either end. Ctrl+Shift+Page Up / Ctrl+Shift+Page Down move the active tab left / right, stopping at either end of the strip. Ctrl+Shift+1 to Ctrl+Shift+9 and Ctrl+Shift+0 select a tab directly. Hold Ctrl+Shift to show square number badges; 0 identifies the tenth tab. See browser tabs.
Ctrl+Enter on a focused folder opens it in a new tab and Shift+Enter in a new window; keypad Enter works too. Ctrl+Shift+Enter does nothing, although the default map opens a new tab with it. On a file, Ctrl+Enter and Shift+Enter open it like Enter. The file chooser opens no tab or window; in a folder request Ctrl+Enter chooses the folder (see File chooser).
Files
With an empty fill, y / x / d act on the focused item. Typical flow: cursor or v then motion → y / x → h / l / g h / g 1 → p.
| Key | Action |
|---|---|
| y / x | Yank / cut the selection (or the focused item) |
| p | Paste. Keep Both is focused on conflicts when that button is offered; otherwise Replace is. |
| P | Paste. Replace is focused on conflicts. Ctrl+V does the same. |
| Y / X | Clear copy/cut marks and this process's clipboard payload. Does not wipe another application's clipboard. |
| d / Delete | Move to Trash with confirmation; d d confirms |
| D / Shift+Delete | Delete permanently with confirmation. Its Permanently delete … button is focused. |
| r / F2 | Rename the focused item in the footer prompt |
| a | Create a file. A trailing / makes a folder (stripped before validation). Conflicts error instead of uniquifying. |
| o / O | Open / Open With |
| M / C | Move / copy the selection (or the focused item) to a folder typed in the footer |
| R | Restore the selection (or the focused item) from Trash, with confirmation |
| c c / c n | Copy path / name |
| ; 1–; 9 / ; 0 | Run the first 10 matching custom actions |
| ; t | Open a terminal in the keyboard-focused folder |
| ; c | Compress the selection (or the focused item) |
| ; e / ; E | Extract the archive here / to a folder typed in the footer |
| . / Ctrl+H / Ctrl+. | Show or hide hidden files |
| , a / , m / , s / , e | Sort by name / modified / size / type. Shift reverses. |
| Ctrl+Z | Undo the last file operation |
Press ;, then 1–9 or 0 (tenth slot) to run one of the first ten
custom actions that match the focused item, or the filled selection when one
exists; Shift with the digit works too. The panel over the ;- pill lists them. Matching, order, and
confirmation follow the context-menu catalog: top-level actions come before the
Actions submenu's, and disabled or unavailable actions, filter misses,
non-native locations, and an 11th match are omitted. A vacant slot flashes
No action N and does not run a different action. The digit checks the catalog
and targets again: if the targets changed since ;, it flashes
Selection changed, and if the slot now holds another action, Actions changed;
neither runs anything. A confirming action asks first, and a run shows in Jobs
like one started from the context menu. See custom actions.
; t opens a terminal in the keyboard-focused folder, the pane holding the
cursor, whatever the cursor or selection is on. The panel lists it, then
; c, ; e, and ; E, after the actions. In Trash and other non-local places it flashes
Can’t open a terminal here. Ctrl+Alt+T keeps its own rule and prefers a
single selected folder; see Not bound for where it still works in this mode.
; c opens the Compress dialog for the fill, or the cursor item when nothing
is filled; items without a local path flash Can’t compress these items.
; e extracts one archive beside itself, as the context menu's
Extract here does, and selects the result: a single top-level entry lands
as-is, and several land in a folder named after the archive. ; E opens extract to › for
that archive. Both take the one-item fill or the cursor item: a larger fill
flashes Extract one archive at a time, and anything that is not a local
archive flashes Not an archive. Empty folders flash Nothing to compress /
Nothing to extract.
M (move to ›) and C (copy to ›) fix the fill, or the cursor item
when nothing is filled, when the prompt opens; Up / Down choose among the
listed folders and never move the cursor away from them. Typing lists
destination folders through the folder picker. Enter
moves or copies into the chosen folder and keeps you in the current one; a moved
cursor item hands the cursor to its neighbor, as d does, without adding the
neighbor to the fill. Conflicts ask as p does, with Keep Both focused when it
is offered. Neither prompt lists the folders being sent or anything inside them,
and M does not list the folder the items are already in. A typed path is
still checked: a path ending in / that does not exist (No such folder), a
file (Not a folder), a move back into the source folder
(Already in this folder), or a folder inside one of the moved or copied
folders (Can’t put a folder inside itself) keeps the prompt open with the
reason. Text that names no existing folder, such as /tmp/newdir or nowhere,
does not show No such folder: Enter acts on the chosen match from the
list, or shows No matching folders when nothing is listed. Empty Enter
closes the prompt. Escape, focus
leaving the prompt, another prompt, leaving the mode, or closing the window
discard it. Items that cannot be moved flash Can’t move these items; an empty
folder flashes Nothing to move / Nothing to copy. ; E's extract to ›
uses the same picker and rules and also stays in the current folder.
R restores the fill, or the cursor item, from Trash through the same
confirmation as the context menu's Restore. Outside Trash it flashes
Only items in Trash can be restored; an empty Trash flashes
Nothing to restore.
, a / , m / , s / , e sort the focused pane by name, modified time, size, or type, ascending; with Shift (, A / , M / , S / , E) descending. The pane keeps its cursor and fill, other open Miller columns keep their order, and the choice is saved like a sort chosen from the pane menu or a List heading: for this folder when Remember sort and icon size per folder is on (the default), otherwise as the default sort. In Trash, Recent, remote shares, and other folders that are not remembered, it lasts while the column is open. List headings show the new sort, so clicking one afterwards reverses what is actually applied. . / Ctrl+H / Ctrl+. change the saved hidden-files preference in every window, including over f results; clearing a filter never reveals hidden files on its own.
y / x / d / c c / c n take the focused pane's fill, or its cursor item when nothing is filled, including on f and s results. A hovered row, a parent folder, and a Miller column's open-path marker are never targets. y and Ctrl+C show the copy icon on those items, and x and Ctrl+X show scissors; cut wins when both could apply. The marks follow view changes and every window, and go away when another application takes the clipboard. Nothing moves until a paste completes, and a completed cut move clears its marks.
p / P / Ctrl+V paste into the same directory as the default map's Ctrl+V (see keyboard navigation), and pasting never changes pointer or keyboard ownership. Focusing a conflict button does not choose it: nothing changes until you accept, and Cancel or Escape leaves both items untouched. Keep Both is offered only for copies.
d / Delete show a Move … to Trash? confirmation (for example
Move 3 items to Trash?) with its confirm button focused; pressing d again confirms it, so d d trashes. D / Shift+Delete, and d inside Trash, show the permanent
deletion confirmation with its confirm button focused, so Enter confirms, and d
there does nothing. In a folder whose listing reports no Trash support (such as
a tmpfs), d / Delete open a permanent confirmation instead, stating
that the location doesn't support Trash, with Cancel focused, so d d does
not delete there. Errors appear in
the usual operation dialogs, and Ctrl+Z undoes what the default map can undo.
In Columns, d with focus in an open folder's empty child column asks to
trash that folder. While f or s results show no hits, d and D
flash Nothing to delete and leave the open folder alone.
a opens create › in the footer. Enter creates an empty file with exactly
the typed name in the keyboard-focused folder; spaces and Unicode are kept. A
trailing / makes a folder instead and is removed before the name is checked. An
empty name, ., .., or a name containing / keeps the prompt open with the
reason, and so does a name already taken (including by a broken link), which
shows “…” already exists, so you can fix it. Nothing is renumbered, replaced, or followed. Escape, focus leaving
the prompt, a clicked row, another prompt, leaving the mode, or closing the
window discard the name. Ctrl+Shift+N still adds a numbered new folder
and renames it in place. Trash and Recent flash Can’t create items here.
r / F2 open rename › in the footer for the focused item: the cursor
item, or the focused f / s hit, never the fill, a hovered row, or an
open-path marker. The current name is filled in with a file's stem (or a
folder's whole name) selected, as inline rename selects it. The item is fixed
when the prompt opens; Up / Down do not move the cursor while it is open.
Enter renames the item to exactly the typed name and keeps its contents; an
unchanged name does nothing. An invalid name keeps the prompt open with the
reason, and a name already taken shows “…” already exists; nothing is replaced. Permission errors and
filesystem limits leave the original name and show the usual rename error.
Escape, focus leaving the prompt, a clicked row (which keeps its selection),
another prompt, leaving the mode, or closing the window discard the typed name.
Trash items flash Can’t rename items here. The context menu's Rename and a
new folder from Ctrl+Shift+N still edit the name in place.
Empty folder: y / x / d / r / Space flash
Nothing to yank / cut / delete / rename / select, and c c /
c n flash Nothing to copy. i in an empty
folder does nothing; on an unpreviewable file it flashes Nothing to preview. In
List and Columns, empty-folder and unpreviewable-file l / Right flash
Nothing to preview. With an empty clipboard, p and P flash
Nothing to paste. x on items that cannot be cut flashes
Can’t cut these items.
O looks up file types and application choices asynchronously for the fill,
or the focused item, and opens the Open With chooser without launching anything
itself. For a mixed selection, Recommended Applications contains handlers shared
by every selected type; Other Applications remains available for an explicit
choice. A new key, selection/focus change, navigation, mode exit, or closed
window prevents an older lookup from opening a chooser over the new interaction.
Unreadable files and broken links flash an error instead of guessing a type from
the first item, and so does a selection no application can open. An empty
folder flashes Nothing to open.
Places
Press g, then a second key. The chord stays armed while the footer g-
pill is showing beside the 10X pill, and a panel over the pill lists the valid second keys; it
never takes focus, so the next key still completes the chord. While the sidebar
shows full rows, not the narrow icon rail it collapses to when the window runs
short of room, keycaps appear on Home (h), Downloads (d), Trash (t), Network (n),
Recent (r), Documents (k), Music (m), Pictures (p), Videos (v), and
visible PINNED rows (1–9 in display order). ,, c, and ; show
the same kind of list (sort options / copy path or name / matching custom
actions) while armed. The second key completes only that chord: , a /
, m / , s / , e sort instead of create / search, and search-result
j / h cannot steal a pending g, c, ;, or t. Sort-chord , n /
, t cancel with Unknown chord.
| Second key | Destination |
|---|---|
| g | First item |
| f | Follow search result: open the folder holding the hit under the cursor, with that item selected. Ends the search. Without hits: Nothing to reveal. |
| h | Home |
| d | Downloads. Missing: No Downloads folder. |
| c | Config (~/.config). Missing: No .config folder. |
| t | Trash |
| n | Network |
| r | Recent |
| k | Documents. Missing: No Documents folder. |
| m | Music. Missing: No Music folder. |
| p | Pictures. Missing: No Pictures folder. |
| v | Videos. Missing: No Videos folder. |
| 1–9 | Visible PINNED rows in sidebar order. Missing: No pin N. |
| + / − | Pin / unpin the folder under the cursor, or the focused pane's folder when the cursor is on a file or the pane is empty |
| Space | Footer go › — pick a folder with the folder picker, or type a path or URI |
| Escape | Cancel |
An unknown second key cancels with Unknown chord.
g + (also keypad +) adds the folder to PINNED and reports its g
digit when it is among the first nine visible pins, for example
Pinned “Projects” as g 3; a pin beyond the first nine flashes
Pinned “Projects” with no digit. g − (also keypad −) removes it and
flashes Unpinned “Projects”. A folder already pinned flashes
“Projects” is already pinned; unpinning one that is not pinned flashes
“Projects” isn’t pinned. g then Shift+keypad + or Shift+keypad −
neither pins nor unpins. Where a top-row key types + or −, as on
AZERTY, g then that key pins or unpins instead of opening a pin. The digit
steps also accept Shift with the digit. Home, the standard folders, Trash, and
other places with their own sidebar rows flash Can’t pin “…”.
g Space opens go › in the footer instead of toggling the selection.
Typing never navigates; it lists matching folders through the
folder picker. Enter, or a click, opens the chosen folder.
When nothing is listed, such as for a URI or a path no folder matches, or when
the typed path names an existing file or folder, Enter submits the text through the same navigation as the location bar
(Ctrl+L). . and .. in a local path resolve as text, without checking the
filesystem. A path naming a file opens its folder with the file selected, and
URI input is submitted unchanged, except that a password typed in the URI moves
into the mount operation instead of the location. A missing or unreachable
destination shows the location bar's error and leaves the current folder open.
Empty Enter just closes the prompt. Escape cancels without navigating;
clicking a listing row ends the prompt and keeps the clicked selection. The
entry is cleared on submit, Escape, focus loss, a replacing prompt, and mode
exit, and it keeps no undo history, so reopening the prompt or another window
cannot recover typed credentials. Anything that looks like a URI (scheme://,
a scheme the location bar opens such as sftp:, //host, \\host, or
user@host:) lists nothing and is never searched,
mounted, or probed before Enter.
Prompts
Typed commands use the footer, never the pane filter revealer or the global search dialog. Enter submits, Escape cancels. Up / Down move the listing or pick a history candidate without leaving the prompt. Clicking a listing row closes the prompt and keeps that selection. An Enter that an input method uses while composing does not submit the prompt; one it passes back does. While a footer prompt has focus, ~ is typed into it; F1 still opens the reference.
| Key | Action |
|---|---|
| / / ? | Find next / previous name in this listing. Does not hide rows. Enter keeps matching substring highlights; Escape from the listing dismisses them. |
| n / N | Repeat the last find. N reverses. |
| f | Fuzzy name filter for this folder (hides non-matches). The footer shows filter: … until dismissed. |
| s | Fuzzy path search below the current folder (cap 100). The footer shows search: … until dismissed. Prompt Escape keeps hits; listing Escape follows the precedence above. |
| z | Jump to a visited folder (name match, then frecency) |
| Z | Jump to a recently visited folder (last visit first) |
| a | Create |
| r | Rename |
| M / C | Move / copy to a typed folder (move to › / copy to ›) |
| ; E | Extract the archive to a typed folder (extract to ›) |
| Up / Down | Choose a listed folder in the go, jump, recent, move, copy, and extract prompts |
| Tab | Write the chosen folder into the go, move, copy, or extract prompt |
/ is a cursor jump; f hides non-matches. The prompt covers the footer and
stays focused while you type. Matching is a case-insensitive substring of the
name, searched in display order from the cursor and wrapping at either end.
Matching substrings stay highlighted in the theme's accent color after Enter in
Columns, Icons, and List. Escape from the listing dismisses those highlights without hiding rows.
Empty / with Enter closes the prompt and changes nothing. Escape from the
prompt cancels without leaving highlights. Pressing / again shows the
prompt. n repeats the last query, including multi-character input, in its
original direction; N reverses it, and either shows the highlights again.
A miss reports No matches for “…” and leaves the cursor where it was.
n / N before any find flashes No previous find. Moving
focus out of the prompt (clicking a row, another pane) discards it; the
committed query is kept per tab and forgotten when the mode is left.
f filters as you type. Enter on f commits the filter, closes the prompt, and returns keyboard focus to the filtered listing (its first result once the results arrive) without opening an item. A following Enter opens the focused item. Opening f again pre-fills the current query. Empty Enter, Escape from the prompt, or Escape from the list clears it. Moving focus out of the prompt keeps what was typed. View rebuilds keep the filter and the funnel collapsed. While a filter is active, the footer count is the displayed result count, including zero, with a file/folder breakdown in its accessible description; motion, Enter, and Ctrl+R act on the results, never on the hidden directory's cursor or fill.
s always searches the current folder tree, not every indexed root, and
matches paths below it the way fzf does: each space-separated term must match
somewhere in a hit's path, in any order, as a fuzzy subsequence, so
git trading readme finds git/trading/README.md. Each term is tried
against the hit's name first, then against its whole path. A term written
'term must appear as one unbroken run of characters, ^term must start the
hit's name or its path, term$ must end it, and !term excludes paths that
contain it. Terms ignore case. Hits whose names match more terms rank
first, then closer matches; among similar matches, folders visited often and
recently, and files inside them, rank higher. The characters a hit's name
matched stay highlighted in the theme's accent color; while find highlights
show, they replace them. Find, f, and s highlights recolor at once
when the theme changes. f uses the same terms and highlights, but never
recurses: it ignores Include subfolders and matches only the names of the
folder's own items, so rep md keeps gamma-report.md. Wildcard filter
patterns do not apply in either. S is unbound; there is no content search.
Enter on s applies the query, closes the prompt, and returns keyboard focus to the results,
on the first hit when there is one. It does not open that hit. A following
Enter opens it through ordinary item activation, not Open search results
directly. Ctrl+K global search is unchanged. Escape from the prompt keeps
the hits so v / V / Space / i can use them (and Right in List and
Columns). From those results, Escape dismisses visual mode, find highlights, and an open
preview before dismissing search, as described above. In List and Columns, h dismisses
search directly unless the preview owns keys, in which case it first returns to
the hits without closing the preview. In Icons, h / j / k / l and
arrows move among the result icons and do not dismiss search or open an item.
Search dismissal restores a previously committed f filter, or the unfiltered
directory otherwise. Empty Escape cancels without retaining search results.
The footer count is the displayed hit count, not the hidden directory's fill.
If another program deletes the cursor's file while the f or s prompt has
focus, focus stays in the prompt. If another program renames or moves the
searched folder, the s search ends; a search in a shallower Columns column
stays.
At its left end, the footer shows the search hit under the cursor as a path
relative to the searched folder. When space is short, an ellipsis replaces the
end of its folder part so the file name stays readable; the accessible name has
the full path. While focus is outside the hits, such as in a menu, the sidebar, or F1, the
footer keeps the last hit the cursor rested on. f filters show no path. Pressing s again while hits are showing
pre-fills their query. A new query,
navigation (including opening a directory hit), leaving the mode, or closing the
window discards the previous query's pending hits; a view change keeps the
search. A folder without a local path, such as Network, flashes
Nothing to search.
z (jump ›) and Z (recent ›) pick from the folders Strata has
opened, the same saved history as the default map's Ctrl+Shift+K, not a
zoxide database. They match each folder's full path with the same terms as
s: space-separated fuzzy terms in any order, 'term, ^term,
term$, and !term, so z dev str finds ~/dev/strata. z ranks
folders whose names match more terms first, a name typed exactly first among
those, then by how often and how recently each folder was opened; Z keeps
matching folders in last-visit order. The folder already open is left out. Candidates list above the footer
as you type, including for empty input, with the first one chosen. Up /
Down choose another row (wrapping) while the entry keeps focus, and the
footer shows the position, such as 2 of 5. Enter or a click opens the
chosen folder once. Editing the text lists
fresh candidates and chooses the first again. A miss shows
No matching folders, and Enter then leaves the prompt open without
navigating. Escape, focus loss, a replacing prompt, and leaving the mode close
the prompt without opening a candidate.
Folder picker
g Space, M, C, and ; E pick a folder from a list above the
footer, like z. Typed text is matched against the paths of folders below the
open folder with the same terms and ranking as s, but only folders are
listed (up to 100). Folders that .gitignore or .ignore files exclude, and
generated trees such as node_modules/, target/, and .cache/, are not
listed; type their path to choose them. A folder the whole query names outright comes first: one at
exactly that path below the searched folder, then any with exactly that name,
however often other folders were visited. Hidden folders are listed when the
listing shows them or a term starts with .. Searches from / skip /proc,
/sys, and /dev, and a search below a typed path starts once typing pauses.
Other text with a colon, such as 10:30, is an ordinary query.
Text that starts as a path (/, ~, ~/, ./, ../, or just ..) moves the
search: everything through its last / names the folder to search below, and
the rest is the query, so /etc/ss searches below /etc for ss and
~/dev/ str searches ~/dev. . and .. resolve as text. With
nothing after the last /, as in /etc/, the list starts with that folder
itself (unless a move or copy would refuse it), then the listed folders below
it, the most visited first and then the shallowest. Without an open local folder, such
as in Trash, only absolute paths and ~ / ~/ paths work. Other text,
including ./ and ../, shows Type a full path here. Another user's home (~name)
shows Only ~ and ~/ are supported, and M, C, and ; E show
Only local folders can be chosen for a URI.
The first folder is chosen. Up / Down choose another (wrapping) and the
footer shows the position (2 of 5); results that arrive later keep that
choice while it is still listed. Tab writes the chosen folder into the
prompt as ./…/ below the open folder, ~/…/ below home, or an absolute path,
always ending in /. That lists the folder first and searches inside it as you
type more; Tab never acts on it. Enter or a click acts on the chosen
folder. When the typed path names an existing item, Enter acts on it at once
unless another folder was chosen with Up / Down. Otherwise Enter
before the search finishes waits for it, so a better match found late still
wins. While nothing is found yet the footer shows Searching…,
and a finished search with no folder shows No matching folders. Editing the
text, Escape, focus loss, a replacing prompt, leaving the mode, and closing the
window cancel a search, and a late result never changes the list.
Search results
While s results are showing:
| Key | Action |
|---|---|
| j / k | List and Columns: move the result list. Icons: move to the next result icon in that direction. |
| l / Right | List and Columns: open a directory hit, or enter a file hit's preview when possible. Icons: move to the next result icon. |
| Enter | With focus already on the results, activate the focused hit once through ordinary open. Enter in the f or s prompt only applies that prompt. |
| i | Directory hit: open an unfocused Miller column, or toggle folder peek. File hit: toggle the preview. Neither takes preview ownership. |
| h | List and Columns: leave preview keyboard ownership, or dismiss search (restoring an earlier f filter if present). Icons: move to the next result icon. |
| g f | Follow search result: open the folder holding the focused hit and select it there. Ends the search without restoring an f filter, so the item is visible; H returns. |
Space does not preview search rows. Use g g / G to reach the first / last result; Home / End and paging keys are swallowed on result lists rather than moving the hidden directory cursor. Ctrl+R inverts f matches, but is inactive for recursive s hits. Once the preview owns keys, its scrolling map takes precedence.
Sidebar and surrounding controls
Arrows and h / j / k / l stay in the Columns, List, and Icons panes. Tab moves from the file list to the window header. Shift+Tab stays with the files. From the footer or other chrome outside the header and sidebar, the next Tab or arrow key returns to the file list.
Ctrl+N shows or hides the sidebar, like the header toggle, and passes through while the preview owns the keys. Ctrl+B pages up instead of toggling it. Ctrl+Shift+B focuses the sidebar when it is visible; a hidden sidebar stays hidden. Pressing Ctrl+Shift+B again returns to the files. The sidebar toggle's tooltip reads Toggle sidebar (Ctrl+N) while the mode is on and Toggle sidebar (Ctrl+B) while it is off, in windows and in the file chooser.
In the sidebar, j / k and Up / Down move between places and device controls. l, Enter, and Space activate the focused place or device control. h, Left, and Backspace return to the files. Returning without activating keeps the file selection. After a place opens another folder, focus is on that listing. Menu or Shift+F10 on a focused sidebar place, Trash, or drive row opens that row's context menu.
On a header control, Enter and Space activate it. h and j return to the files and do not change directory or run a file operation.
After you return from another window, g, f, and s act on the listing without first clicking a row.
Ctrl+L still edits the location bar. Menus, dialogs, text fields, and the shortcut reference keep their own keys. The file chooser uses these same round trips.
File chooser
The portal file chooser follows the saved preference, and live changes to it, without opening Settings. While the mode is on, a footer under the files carries the same prompts, chords, and feedback, and the pane chrome hides as in a window. Accept, Cancel, the header close control, and List headings stay. Ctrl+Shift+M works in the chooser, even from the name or location field. Turning the mode off there keeps the request open, hides the footer, and restores the chooser's own keys. Lowercase q neither ends the request nor leaves the mode.
The chooser uses this map within the request's limits. A key the request does not allow is refused when it is pressed, not only hidden:
| Key | In the chooser |
|---|---|
| Enter / o on a file | Choose the file instead of opening it. In a multiple-file request with a fill, choose the fill. |
| Enter / o on a folder | Open it. Ctrl+Enter or Accept chooses a folder in a folder request. |
| Enter in a Save request | Save in the current folder, whatever the cursor is on. In Recent, save in the folder of the filled or cursor file. An existing file asks first. |
| o on a file in a single-file Save request | Save over that file. It asks first. |
| r / F2 in a single-file Save request | Edit the name, with the part before the extension selected. Enter saves; Escape returns to the files and keeps the edit. |
| Escape | Take one dismissal step from Escape precedence, then cancel the request. The automatic first-row selection is not a step. |
| Space, v / V, Ctrl+A, Ctrl+R | Only in requests that let you choose several files or folders. Otherwise, Save requests included, Only one item can be chosen. |
| a, r / F2, d / D / Delete, , sorts, ., c c / c n | As in a window, except r / F2 in a single-file Save request. |
| g places, g Space, z / Z | Local folders and Recent only. Trash, Network, and remote pins flash Only local folders can be opened here; a typed remote location shows the unsupported-location error. |
| y, x, p / P, Y / X, M / C, R, g + / g −, Ctrl+C / Ctrl+X / Ctrl+V, O, ;, i, Q | Not available in the file chooser. The chooser does not copy, move, or restore files, change pins, open them with an application, run custom actions, peek folders, or open an extra Miller column, and Q does not close the chooser: cancel with Escape, Cancel, or the close control. |
| Ctrl+K, Ctrl+Shift+K, Ctrl+,, Ctrl+Z | Unbound. |
The request takes the fill, or the cursor item when nothing is filled; the automatic first-row selection never counts. A Save request saves in the current folder; in Recent, which has no folder of its own, it saves in the folder of the filled or cursor file. Outside Recent, moving the cursor changes neither the name nor the destination. While the name or location field has focus, every key but F1, Ctrl+Shift+M, and Escape is left to the field; Ctrl+A selects the text. Every request starts with focus in the files. Tab goes from the files to the header, and from the header to the Name field when the request has one (a single-file Save request or a file Open request). From the Name field, Tab follows the dialog's ordinary focus order to the next control, and Escape returns to the files with the edit kept. Saving over an existing file asks first with Cancel focused. Beside Cancel and Save, a Save request shows hints for Enter, plus r and o when it saves one named file.
f and s hits follow the request's folder-only and file-type limits. F1 shows a reference listing only the keys the request allows; Escape closes it without canceling the request. The g panel leaves out g t, g n, g +, and g −.
Still bound
These GUI conventions stay available alongside the Yazi verbs:
| Key | Action |
|---|---|
| Ctrl+C / Ctrl+X / Ctrl+V | Copy / cut / paste the selection as in the default map. Ctrl+V focuses Replace on conflicts, like P. |
| Delete / Shift+Delete | Trash / permanent delete (same as d / D, with confirmation) |
| F2 | Footer rename (same as r) |
| F5 | Refresh |
| Ctrl+L | Edit the location bar |
| Ctrl+K | Global search |
| Ctrl+1 / Ctrl+2 / Ctrl+3 | Columns / Icons / List |
| Ctrl+Shift+N | New folder |
| Ctrl+Alt+N | New folder containing the selection |
| Alt+Enter | Properties |
| Menu / Shift+F10 | Context menu |
| Ctrl++ / Ctrl+− / Ctrl+0 | Text size |
Context-menu shortcut hints follow this map (x cut, y yank, p paste, d / D trash / delete, r rename, M / C move / copy to, R restore, i quick preview, next column, or folder peek). The file chooser has no i preview, so its Quick preview item shows no hint. Duplicate, Copy path, Pin to sidebar, and Open in Terminal show no hint, because their default keys (Ctrl+D, y, p, Ctrl+Alt+T) are remapped or not part of this map; Space for preview and Ctrl+R for rename are hidden too. Use c c to copy a path and g + to pin. Properties keeps Alt+Enter.
Not bound
These default-map shortcuts are unbound or remapped while the mode is on:
| Default-map key | In 10xer mode |
|---|---|
| Ctrl+Shift+K | Unbound. Use z / Z. |
| Ctrl+Alt+T | Does nothing while a text field such as the location bar has focus, or while search results are listed. From the file list or the sidebar it still opens a terminal, as in regular mode. Use ; t or the context menu. |
| Ctrl+\ | Unbound. Arrows never leave the file list. |
| Ctrl+D | Half page down. Duplicate has no key; use Duplicate in the context menu. |
| Ctrl+F | Full page down. Filter is f. |
| Ctrl+B | Full page up. Sidebar toggle is Ctrl+N. |
| Ctrl+R | Invert selection. Rename is r / F2. |
| y / p (default map) | Yank / paste. Path copy is c c; pin with g + and jump to a pin with g then a digit. |
| Space | Toggle selection. Preview is i on a file; in List and Columns, l / Right also open it and move the keys into it. |
Archives
Extraction safety
Archive member paths are untrusted metadata. If an extractor joined a selected
folder with ../report.txt unchanged, the filesystem would resolve the result
beside that folder instead of inside it. This archive path-traversal pattern is
also known as Zip Slip.
Strata resolves parent components without allowing them to walk above the
selected destination. For example, both ../report.txt and
folder/../report.txt become report.txt. Extraction then continues with later
members instead of aborting the entire operation. Backslashes count as path
separators, so ..\report.txt also becomes report.txt. An empty or absolute
path, or one with any component that starts with a letter and a colon, such as
C: or docs/a:b.txt, fails the extraction with "Refusing unsafe archive
path: <name>", and nothing is written outside the destination. A path that resolves to nothing, such as folder/.., fails it
with "Refusing empty archive path: <name>".
The sanitized path still passes through the descriptor-relative destination
writer, which refuses symlink traversal. Normal conflict renaming also applies,
so two members that sanitize to report.txt become report.txt and
report (2).txt rather than overwriting one another.
Extraction output
Strata writes members into a hidden .strata-extraction-<id> folder inside the
destination, created when the first member is written. It is visible during
extraction only when hidden files are shown. When the archive has been read,
Strata publishes the folder:
- A single top-level entry is moved up into the destination under its own
name. It is renamed to
name (2),name (3)and so on only if the destination already has an entry with that name, including a symlink or special file, which is never followed or replaced. - Several top-level entries stay together in a folder named after the archive
without its extension, such as
photos/forphotos.zip. If that name is taken, the folder becomesphotos (1)/,photos (2)/and so on. Entries inside the folder keep the archive's names, even when the destination already has an entry with the same name; only duplicates within the archive are renamed. - If extraction fails or is cancelled after writing a file, everything written
so far stays in the archive-named folder, even if it is a single entry. The
error message ends with
Extracted entries remain in “<folder>”., and the "Operation cancelled" dialog counts the entries completed, failed, and not attempted. If no file was written, any folders created along the way are removed and nothing is left behind. - If extraction stops because a password is missing or incorrect, everything
written so far is discarded, including members that were not encrypted.
The password prompt extracts the whole archive again, so the retry lands
under the archive's own name instead of
photos (1)/. Damage in a member that is not encrypted is reported as damage, even when a password was given. If the output cannot be removed, the failure is reported like any other, with the reason and the folder that keeps the output, and no password prompt opens.
Publication never replaces an existing entry. On a filesystem without atomic
no-replace renames, such as an ntfs-3g mount, the result is the same: a single
root folder publishes as name, then name (2) when taken, and several
top-level entries publish in photos/, then photos (1)/. Strata creates the
target folder exclusively and links each extracted file into it, recreating
symlinks with their stored targets and subfolders with their mode and
modification time, so a read-only folder such as mode 0555 keeps its mode.
The existing same-named folder is untouched, and no .strata-extraction-<id>
folder remains. If this publication fails partway, the partial target folder
is removed and the error ends with
Extracted entries remain in “.strata-extraction-<id>”.
Partial output from any other failed attempt stays in its own folder, so a retry never merges into it. An archive with several top-level entries is extracted into the next numbered folder; a single entry lands in the destination under its own name, as usual.
.tar.gz archives are read to the end of the gzip stream, including every
member of a multi-member file such as concatenated .gz output, so each
member's CRC32 and length trailer is verified. A mismatch or a truncated trailer is
reported as a damaged archive. Zero bytes after the last member, as tape
blocking or dd leave them, are padding rather than damage; any other
trailing bytes are reported as a damaged archive. Members already written are
kept as described above, but their contents are unverified.
A TAR whose first entry is ./ extracts its contents. A git archive or
GitHub tarball extracts without a pax_global_header file. Every member of a
solid 7Z archive is extracted.
Damaged and oversized archives
A text file renamed to .zip, or a malformed or truncated archive, fails with
"This file is not a valid archive or is damaged." A ZIP or 7Z whose declared
total size exceeds the destination's free space fails before any member is
written. A member that produces more or fewer bytes than its header declares
fails the extraction and is not kept. There is no compression-ratio or
entry-count cap: a highly compressible archive with truthful headers extracts
in full.
Undo
Ctrl+Z after a completed extraction, whether it started from Extract here,
Extract to…, Enter, double-click, or a password retry, moves the published
output to Trash: the single top-level file or folder, or the one archive-named
folder such as photos/. Only what the extraction published goes: if
readme.txt was published as readme (2).txt beside an existing one, only
readme (2).txt is trashed. Ctrl+Shift+Z after that undo restores the output
from Trash. An extraction that published nothing, failed, or was cancelled
records no undo entry, so Ctrl+Z undoes the operation before it and leaves any
kept partial output in place.
Links, permissions and times
Symbolic links are recreated with their stored targets, including absolute
targets and targets outside the archive, and are never followed by later
members: a member under a link name fails instead of writing through the link.
TAR names and hard-link targets retain their native bytes. Hard links become
links to the member of that name extracted earlier from the same archive,
following any conflict rename. A hard link to a member that
was not extracted, or that appears later, fails the extraction. A TAR FIFO or
device member fails the extraction with "Archive member “<name>” is a FIFO and
cannot be extracted" or "… is a device and cannot be extracted". An existing symlink at a member's name, such as an
earlier link member with the same name, is skipped like a file: the member is
renamed to name (2).
Each member gets its stored permission bits, masked by the umask, with setuid, setgid and sticky bits removed, and its stored modification time. ZIP times come from the Info-ZIP extended timestamp, then the NTFS field, then the DOS time read as local time. Members without a stored mode keep the default permissions. Folder permissions and times are applied only when extraction completes, so partial output from a failed or cancelled extraction stays writable. A folder listed more than once in the archive is restored once: each of its permissions and time comes from the last entry that stores it. Folders created only as parents of other members keep default permissions. Owner, group, access times, extended attributes and ACLs are not restored. RAR archives restore permissions and times, but a member archived without Unix mode bits, such as one made on Windows, keeps the default permissions, and link members still extract as regular files.
On filesystems that cannot store Unix permissions or times, such as FAT and
exFAT, those are skipped without an error, as tar and unzip do. Links
cannot be skipped: an archive with links fails there, naming the member, and
keeps the output written so far.
Extraction targets
Extract here and Extract to… in the item context menu, the 10xer ; e
and ; E chords, and extraction on Enter or double-click apply only to a
regular file, or a symlink to one, with a local path and a .zip, .7z,
.tar, .tar.gz, .tgz, or .rar extension, in any letter case. A folder
named photos.zip opens like any other folder and offers no Extract actions.
FIFOs, sockets, devices, and broken links named like archives are not
extracted either. In Icons and List views, Enter or double-click opens them
externally. In Columns, Enter opens the preview for one with a ZIP, 7Z, TAR,
or TAR.GZ name, and double-click opens it externally. The chords report "Not
an archive".
If the item changes between opening the menu and running the action, the
operation layer checks the path again. A path that exists but is not a regular
file fails with Not an archive: “<name>” before any destination folder is
created.
Extract here and Extract to…
Extract here extracts beside the archive, reloads the folder, and selects the result. The selected result keeps keyboard focus after the progress dialog closes, including in Columns. Extract to… opens a floating folder chooser titled "Extract to", with an Extract here button and New Folder. After extraction, the window navigates to the chosen folder and selects the result. Cancelling the chooser starts no extraction. A destination reached through a symlink receives the output in the resolved folder.
Enter and double-click
In Icons and List views, Enter or double-click on an archive extracts it as Extract here does, instead of opening an external application. In Columns, Enter on a ZIP, 7Z, TAR, or TAR.GZ archive opens its preview; Enter on a RAR archive extracts it, and double-click extracts any archive. In the file chooser, activating an archive selects it as a file. Activating the same archive again never writes into an earlier extraction.
10xer mode
In 10xer mode, ; c opens the Compress dialog for the targets. If any target
has no local path, it flashes "Can’t compress these items", and an empty folder
flashes "Nothing to compress". ; e extracts
one archive beside itself and selects the result, and ; E extracts it to a
folder typed at the extract to › prompt. Unlike Extract to…, ; E
leaves the window in the current folder. The prompt chooses and checks a
folder as move to › and copy to › do; see Files and
Folder picker in 10xer mode. With several targets, ; e and
; E flash "Extract one archive at a time". With one target that is not an
archive, such as notes.txt or a folder named photos.zip, they flash "Not an
archive". With no target, as in an empty folder, they flash "Nothing to
extract".
Passwords
Extracting a password-protected ZIP, 7Z, or RAR first runs without a password, then opens a password dialog titled Extract with the archive's name. Submitting an empty password keeps the dialog open with "Enter a password". A wrong password reopens it with "Invalid password", including for plain-header 7Z and ZipCrypto archives. Cancelling the dialog after Extract to… leaves nothing in the chosen folder, and the next extraction does not navigate there. Closing the dialog with Cancel or Escape leaves keyboard focus in the file list. A click outside the dialog closes it like Cancel only while the password field is empty; once you have typed a password, a click outside leaves it open.
Only a failure that the decoder reports as a missing or incorrect password opens the password prompt, with "Invalid password" for an incorrect one. The wording of an error message never decides it, so a member or archive name containing "password" cannot open the prompt.
RAR
RAR archives extract like the other formats, with the same output and
conflict rules. Encrypted contents or encrypted headers open the password
dialog, and a damaged unencrypted RAR fails with "This file is not a valid
archive or is damaged." without a prompt. Cancelling a RAR extraction stops it
at once and reports it as cancelled. Extraction fails if the decoder sends no
data for 30 seconds, if a member continues into another volume of a
multi-volume RAR ("The next RAR volume is missing"), or if the archive's
dictionary exceeds the decoder's memory limit ("RAR dictionary exceeds the
decoder's memory limit"). Official release builds and AUR builds include RAR extraction. A build made without RAR support shows no Extract actions for
.rar files, and Enter or double-click opens them externally.
Archive creation
Compress… appears in the item menu only when every selected item has a
local path. The Compress dialog offers ZIP, 7Z, TAR.GZ, and TAR, with ZIP
selected and the name prefilled with the item's name, or archive for several
items. Typing the selected format's extension, such as backup.zip with ZIP,
creates backup.zip, not backup.zip.zip. A name such as ../outside is
rejected in the dialog, and nothing is written outside the shown folder.
Protection (No password / Password protected) shows only for ZIP and 7Z;
switching to TAR or TAR.GZ hides it and resets it to No password. Password
protected with an empty password shows "Password required", and fields that
differ show "Passwords do not match"; no archive is written.
The new archive appears only when encoding finishes. If you have not navigated away from the folder where you started and no other operation has started since, it is then selected and scrolled into view in every view mode. Ctrl+Z after compression moves the new archive to Trash. Closing the Compress dialog opened from the item menu with Escape or Cancel returns focus to the cursor row. A click outside closes it the same way only while the name is still the default and both password fields are empty; otherwise a click outside leaves the dialog open.
Strata chooses compression according to the output container, not just the selected filename extension.
| Output | Payload encoding | Password support |
|---|---|---|
| ZIP | Stored for known already-compressed members; DEFLATE level 6 for other files | AES-256 for either method; filenames remain visible |
| 7Z | Copy for known already-compressed members; LZMA2 level 6 for other files | AES-256 for both methods, plus encrypted headers |
| TAR | No compression | None |
| TAR.GZ | One gzip member containing the entire TAR stream; stored DEFLATE blocks when all regular-file payloads are known already-compressed, otherwise default gzip compression | None |
| RAR | Extraction only | No RAR creation |
A password-protected 7Z is compressed before it is encrypted, so it is about as small as an unprotected one, and it lists no member names without the password.
ZIP and 7Z can mix methods in one archive. 7Z currently writes independent, non-solid members: one file cannot borrow another file's compression dictionary. LZMA2 streams on the compression worker rather than buffering 64 MiB jobs for additional codec threads. Its dictionary is capped at the member's size (minimum 4 KiB, maximum the level-6 default of 8 MiB). This avoids oversized per-file setup and keeps worker lifetime tied to the operation. It does not parallelize large individual members.
Gzip has no per-file method field. A mixed TAR.GZ therefore compresses all TAR bytes, including any already-compressed members. The all-compressed fast path still emits a valid gzip header, DEFLATE stream, checksum and trailer, not raw TAR or concatenated per-file gzip streams. It trades a little size overhead, including uncompressed TAR metadata/padding, for avoiding recompression. TAR retains its existing sparse-file and symlink handling. Choose ZIP or 7Z when per-member compression selection matters for mixed inputs.
Classification and limits
Strata decides by file extension, ignoring case, whether a member is already
compressed. The list covers common compressed
media, compressed archives and compressed document/package formats. Compound
names such as .tar.gz and aliases such as .tgz are recognized. Raw containers
such as .tar, .bmp, .wav, .avi and .iso, extensionless files and unknown
extensions retain compression.
Extensions are hints, not content validation: an MP4/MOV/MKV container can contain uncompressed streams, a PDF can contain plain data, and even a ZIP can contain stored members. Such exceptions may yield a larger output. Strata does not read all payloads to estimate compressibility. The existing preflight walk opens entries to count members and classify names; payloads are streamed once during encoding. Directory recursion remains descriptor-relative and symlinks are not followed. Sources are reopened for encoding, so concurrent source edits can change the usefulness of the preflight gzip choice, but not the output format.
ZIP preserves UTF-8 symlink targets; TAR preserves native symlink targets.
Neither stores the target's contents. 7Z creation rejects symlinks with
7z compression does not support symbolic links: <path>. Use ZIP or TAR instead.
and leaves no archive. A file whose name is not valid UTF-8 fails ZIP and 7Z
with an error that names it and suggests TAR; TAR stores the original name
bytes.
Every format records each member's modification time and Unix mode. ZIP stores
the time as local DOS time, clamped to 1980–2107, plus an Info-ZIP extended
timestamp when the time falls between 1970 and January 2038; TAR records symlink times too; 7Z uses the p7zip Unix-mode
attribute and also stores each member's creation and access times when the
source filesystem reports them.
Existing archive names
When the requested archive already exists, a File already exists prompt offers Cancel, Keep Both, and Replace, with Replace focused. Enter activates the focused button. Escape, Cancel, or X leaves the existing archive unchanged and returns focus to the listed item that was focused before the prompt.
Keep Both publishes the next available numbered name,
such as archive (1).zip or archive (1).tar.gz, and selects that new archive.
It skips existing files, directories, and symlinks, including names that appear
while encoding is running. The completed staging file is retried atomically at
publication; the sources are not compressed again for each collision.
Replace moves the existing archive to Trash before publishing the new one, and the new archive keeps the replaced archive's permission bits. Ctrl+Z brings the old archive back. If the existing archive cannot be moved to Trash, Replace fails and the archive stays in place. Cancelling, or an encoding failure, during Replace also leaves it in place. If publishing fails after the old archive went to Trash, the error says the original is in Trash.
Feedback and cancellation
Compression shows Preparing… while counting members, then Compressing… and
a count such as 1 / 2 files. Extraction opens a foreground dialog titled
Processing archive…. A ZIP shows Processing archive…, then a count such as
3 / 12 files; TAR, TAR.GZ, 7Z, and RAR show Preparing… until the first
member is written, then a running count such as 3 files with no total. After
Cancel, the count stops updating, the title changes to Cancelling operation…,
and the bar pulses. A large member can take time before the completed count
advances. The activity indicator continues animating during that work and finalization; it is not a
byte-level progress estimate.
Progress dialog
Moves, extraction, restore, emptying Trash, and undo/redo keep the foreground progress dialog. An operation on fewer than 16 items shows no dialog for its first 350 ms, and none at all if it finishes sooner; an operation on 16 or more items, or with an unknown item count such as an extraction, shows it at once. Its subtitle reads "Cancelling will not undo completed changes", except when emptying Trash, which reads "This may take a moment". Clicking outside the dialog leaves it, its progress, and Cancel visible, and Escape acts as Cancel. When the dialog closes, keyboard focus goes to the file list's cursor row. If an error dialog opens as it closes, that dialog keeps focus, with Close focused.
During a move, the dialog shows the percentage, transferred and total bytes, "N of M files" with the current file name, and the speed with time left ("Calculating speed…" until a speed is measured). The bar advances as bytes are written, not only after each item. When everything being transferred is empty files or folders, the bar advances by item count instead and reaches 100% only when every item is done; a copy card does the same. With an unknown byte total the bar pulses and reads "Preparing…" until bytes move, then "Transferring…". A move, or an undo or redo that moves items, onto removable media shows "Writing to device…" and is not reported done until the filesystem flush returns.
Cancel during a move, or during an undo or redo that moves items, retitles the dialog "Cancelling transfer…", says "Waiting for the active write to stop. The device may still be writing.", and disables the button as "Cancellation requested". If the move has not stopped 8 seconds later, the title becomes "Device not responding" and the subtitle warns not to unplug the device. While a move or docked copy is still stopping, starting another file operation shows "Transfer cancellation pending" and nothing starts. Cancel on any other operation, such as an extraction, retitles the dialog "Cancelling operation…" and disables Cancel.
Progress cards
Copying, compression, deletion, and drive formatting use independent progress
cards at the bottom right, without a progress modal or a restore action. Browsing
continues while the jobs run. Cards show the full filename/status and destination
(or the drive being formatted), wrapping long text instead of truncating it.
A card also shows its title, a progress bar, and its percentage once, at the
right of its footer. The footer's left label shows a copy's speed, or a
compression's count such as 1 / 2 files; during a deletion it is empty.
After X, a copy's label reads "Waiting for device…" and a compression's count
stops updating. A docked copy also shows files done of total. A copy onto
removable media shows "Writing to device…" in its footer and is not reported
complete until the filesystem flush returns. A compression card names the
archive instead of the first item. The
destination reads "→ <path>" for a folder, "→ Trash" for Move to Trash, and
"Permanent deletion" for permanent deletion. Several cards stack and update
independently; the stack scrolls once it reaches 320 px. A card never blurs
or unblurs the window, even while another dialog is open.
The dock also shows brief notices, such as "Copied to <device>" when a Send to finishes before its progress appears. A notice is a row with a check icon before its text and no controls; clicking it does nothing. Notices and progress cards stack in the order they appear. A new notice in the same window replaces any notice still visible, but progress cards stay. Notice text wraps and is cut to three lines with an ellipsis. When a notice expires and the dock holds nothing else, the dock closes.
The X cancels only its own copying, compression, or deletion job; other cards and the foreground operation continue. Once requested, the card retitles to "Cancelling transfer…" for a copy or "Cancelling operation…" otherwise, and X is disabled while the worker stops. A cancelled copy shows "Device may still be writing. Do not unplug until the operation stops." inside that card, without a separate banner or a Return to browser action. Do not unplug a drive while cancellation or writes are pending. Normal progress and pending cancellation use neutral styling, not error borders or text. When a docked operation is cancelled, its card closes and the "Operation cancelled" dialog described under Cancellation opens. When one fails, its card closes and an "Unable to complete operation" dialog shows the error. If a docked deletion partly fails and you choose Delete Permanently while another operation runs, "Another operation is active" appears and nothing more is deleted.
Formatting cannot be cancelled: its card reads "Formatting drive" and "Do not unplug until formatting finishes." and has no X while formatting runs. On success it reads "Format complete" and "The drive was formatted successfully." and behaves like any completed card. On failure the card closes and an error dialog opens.
A finished copy, compression, or deletion retitles its card "Copy complete",
"Compression complete", or "Deletion complete", with a check icon, a clickable
Complete button, and 100%. Its bar becomes a five-second auto-dismiss
countdown, with "closing in" text; formatting completes the same way. Hovering
or focusing a card pauses the remaining time and shows "paused"; leaving
resumes it rather than restarting the countdown. The pin button, Keep
notification, keeps a completed card until dismissed and shows "pinned".
Complete or X dismisses only that notification, never another operation.
If another operation starts before a docked copy or compression finishes, the
finished one does not select or reveal its result.
Finish or cancel running operations before closing their window. Closing a tab with a docked operation running, or the window while any tab has one, shows "File operations are still active" and closes nothing; closing the window while a drive is formatting shows "Drive formatting is still active". Completed cards are notifications, not active jobs, and do not block window closure.
Cancellation
After a cancelled operation, an "Operation cancelled" dialog gives the counts of items completed, failed, and not attempted, then "Completed changes were not reverted." Every affected source and destination folder refreshes to its on-disk state. An item that finishes copying as Cancel arrives counts as completed, not cancelled.
Cancellation is cooperative. Encoded output and TAR's input-to-encoder writes check cancellation, as do 7Z source reads and existing ZIP copy chunks. Errors from these checks become cancellation results, not corruption/password errors. The UI waits for the worker to return before removing progress and showing the cancellation summary. Compression staging is discarded rather than published, and replacing an existing archive leaves that archive intact on cancellation. Cancelled extraction keeps the members already written inside the archive-named folder described in Extraction output. Individual blocking filesystem calls and codec calls still have to return; cancellation is not an immediate thread kill. RAR extraction is the exception: its decoder runs in a separate process, which cancellation stops at once.
Document previews
Strata can render local Markdown, a deliberately small HTML subset, RTF, CSV, and TSV with native GTK widgets. Each document preview has Rendered and Source views. Render documents by default under Settings → General → BROWSING chooses the initial view for each newly opened document; View source and View rendered in the preview header switch the current document without changing that preference.
Remote files never render. A remote Markdown, HTML, RTF, CSV, or TSV file previews as source only. A remote XLS, XLSX, ODS, or DOCX file is not offered for preview at all: its context menu has no Quick preview item, the preview drawer shows "No preview for this selection" in Icons and Columns view and hides in List view, and in 10xer mode i while the drawer is closed, or l in List and Columns view, shows "Nothing to preview". Copy the file to a local folder to preview it. Rendered previews are selected from the local filename or content type:
- Markdown:
.md,.markdown,.mdown,.mkd,.mkdn,.mdwn,text/markdown, andtext/x-markdown; - HTML:
.html,.htm,.xhtml,text/html, andapplication/xhtml+xml; - RTF:
.rtf,application/rtf, andtext/rtf; - delimited tables:
.csv,.tsv,text/csv, andtext/tab-separated-values.
Local XLS, XLSX, and ODS workbooks use the same table renderer but do not expose a raw Source view. Only the first worksheet is previewed. Formulas are not recalculated, macros are never executed, and workbook styling, charts, and merged cells are not reproduced. Values use Calamine's string conversion, not Excel's full number-format display.
Local DOCX documents render the same way and also have no Source view, since the file is a ZIP container rather than text.
Supported content
Markdown uses pulldown-cmark with tables, strikethrough, and task lists enabled. Headings, paragraphs, emphasis, lists, block quotes, web links, fenced and inline code, rules, tables, and line breaks render natively. Known fenced-code language hints use Strata's existing, theme-aware GtkSourceView syntax highlighting. Every rendered code block has a Copy code button that copies the whole block. Raw HTML is displayed as inert text, with the notice "Raw HTML is shown as inert text in Markdown previews."
Markdown images with relative paths render PNG, JPEG, GIF (first frame), WebP, BMP, and SVG content. Percent-encoded filenames are supported. Image files must be inside the document's folder or its descendants; symlinks cannot escape that folder. Inline images appear below their containing paragraph or list item. Images in tables remain alt-text placeholders. Absolute paths, file: URLs, data URLs, and remote images are not loaded; remote URLs are discarded and the notice "Remote and absolute image URLs are not loaded. Use images inside the document's folder." appears.
Fenced mermaid blocks render offline with mermaid-svg, a native Rust renderer, including flowcharts and sequence diagrams. Diagrams use the active theme's text and surface colors and update live. Copy diagram source copies the original Mermaid text. Unsupported or invalid syntax retains readable source with a fallback notice; the renderer does not promise complete Mermaid.js compatibility.
LaTeX equations use $...$ inline, $$...$$ for display math, or fenced latex/math blocks. Inline equations stay within the surrounding prose; selection/copy preserves the original LaTeX delimiters. Display equations offer Copy equation source. Equations, inline and display, use the active theme's text and surface colors and recolor when the theme changes. Base TeX and AMS notation supports fractions, roots, superscripts/subscripts, sums, integrals, and matrices. Unsupported commands fall back to readable source. Equations in table cells remain source text, and escaped dollars and code spans are not interpreted as equations. This is math notation support, not a full LaTeX document compiler.
RTF is converted in-process to the same HTML subset. Paragraphs, line breaks, bold, italic, underline, strikethrough, \'hh Windows-1252 escapes, and \uN Unicode escapes with their \ucN fallback characters are supported. Font, colour, style, list, and table control words carry no formatting: table cells and list markers become plain paragraph text, and font tables, stylesheets, pictures, headers, footers, footnotes, annotations, and other non-body destination groups are discarded. Code pages other than Windows-1252 are not honoured, so \'hh bytes in a document declaring another code page can decode to the wrong character.
DOCX is read with docx-rs inside the preview sandbox and converted to the same HTML subset. XML namespace prefixes are normalized by URI before parsing, so alternate prefixes and default namespaces preserve Word content. The helper limits both original and normalized XML parts to 64 MiB total and rejects DTDs. Headings (Heading1-Heading6, Title, Subtitle), quote styles, paragraphs, bold, italic, underline, strikethrough, line breaks, bulleted and numbered lists with their nesting level, and tables render natively; the first table row becomes the column titles. Each tab becomes a single space. Hyperlink text is kept but the link target is not, and images, drawings, text boxes, headers, footers, footnotes, comments, field instructions, and theme or style-sheet formatting are omitted. A field's displayed result text is kept. Table cells show their paragraphs joined into a single value. Nested tables inside a cell are omitted. A DOCX whose converted content exceeds the helper's size budget stops at that point and shows "Document preview reached its size budget; open the file to see all content." Legacy DOC, ODT, and presentation formats are not supported.
HTML uses html5gum tokenization and supports semantic containers, headings, paragraphs, emphasis, underline (u, ins), lists, block quotes, http and https links, pre/code, rules, simple tables, and line breaks. Normal flow whitespace is collapsed like HTML, while pre content remains exact. A known language-* class on code inside pre sets the syntax hint. language-mermaid renders a diagram, and language-latex or language-math renders a display equation, as fenced Markdown blocks do. Classes never enable CSS. Entities are decoded before their text is escaped for Pango.
CSS, classes, IDs, metadata, and other presentation attributes are ignored. Scripts, styles, forms, frames, objects, embedded content, images, media, event handlers, unsafe links, and resource-bearing tags or attributes are omitted. If a document still has useful safe content, Strata renders it with the notice "Unsupported or active HTML content was omitted." u and ins render as underline without that notice. Link schemes are checked again when a link is activated before the existing external URI launcher is used.
Limits and fallback
Rendered parsing has fixed limits:
- 1 MiB input;
- 20,000 parser events;
- nesting depth 32;
- 256 columns per Markdown or HTML table row;
- 4 MiB of escaped Pango markup;
- 500 ms parser time.
A truncated, malformed, contentless, timed-out, or limit-exceeding Markdown, HTML, RTF, CSV, or TSV document opens in Source. The view-switch control is hidden and the reason is shown above the source preview. A DOCX has no Source view: when its converted content is empty or exceeds these limits, the preview shows "Preview unavailable" with the reason, such as "Rendered preview exceeded the 20,000 parser-event limit". A cancelled parse, such as one interrupted by selecting another file, is discarded without a result. CSV and TSV skip the parser-event and nesting limits; a row over 256 columns stops the table at that row with the table budget warning instead (see Interactive tables).
Source previews whose language GtkSourceView recognizes, such as Markdown and HTML, use the syntax-highlighted SourceView up to the 1 MiB read limit. Other source previews use SourceView, without highlighting, up to 128 KiB and 512 lines with no logical line over 2 KiB. Larger ones, and files with longer lines, use recycled plain-text rows; long logical lines are fully represented as contiguous 2 KiB virtual rows. A Markdown, HTML, RTF, CSV, or TSV document cut at the read limit shows "Rendered view is unavailable because the document exceeds the 1 MB preview limit." above its Source view. A source preview cut at the read limit shows "Preview limited to the first 1 MB", except a document's Source view in the syntax-highlighted SourceView, such as local Markdown or HTML. A recycled-row preview whose long lines were split shows a notice that long source lines are split into virtual rows for responsive scrolling; when that preview was also cut at the read limit, one combined notice says both. Toggle word wrap in the preview header wraps source and rendered prose for Markdown, HTML, RTF, CSV, and TSV. It defaults to off, applies in every open window, and survives restart. DOCX and workbook previews have no wrap button, and their rendered text does not wrap. In wide previews the Rendered view stops growing at 1280 px and stays centered; Source views and standalone tables keep the full width. Selection and model-backed copy preserve the original line breaks. File reading remains limited to 1 MiB; Open in default application in the preview header opens the complete file. The file chooser's preview has no such button.
When Source is the initial view, parsing is deferred until the user requests Rendered. Rendered paragraphs and code are grouped around a 32 KiB target, while individual pathological lines are divided into contiguous 2 KiB virtual rows before GTK layout; tables remain atomic document-selection units but use their own recycled, vertically scrolling rows, with exceptionally large cell displays bounded while table copy retains complete text. Cell formatting that expands beyond 16 KiB is shown as plain text with an explanatory accessible description. Complete code blocks use syntax highlighting, while blocks split for virtualization remain plain to keep highlighting bounded and lexically correct. Both large source and rendered previews use GTK list virtualization, so only visible rows own Pango layouts, text buffers, table grids, or cells. Drag selection is stored in document coordinates and survives row recycling; copy reads from the model, with tables represented as tab-separated text.
Text selection and find
Rendered prose and code, and large source previews shown as recycled rows, support double-click word selection, triple-click selection of a logical line (a whole paragraph in prose), Shift+click extension, and Shift+Left, Shift+Right, Shift+Up, Shift+Down, Shift+Home, and Shift+End. Ctrl+Shift+Left and Ctrl+Shift+Right extend by words; Ctrl+Home and Ctrl+End move to the start and end of the loaded document. Ctrl+A selects the whole loaded document, and Ctrl+C copies the selection. Selection and copy use document coordinates and survive recycled rows. In 10xer mode, while a document preview owns the keys, these keys still select text: Shift with an arrow, Home, or End (with or without Ctrl), and Ctrl+Home and Ctrl+End, reach the document instead of scrolling it. Ctrl+A and Ctrl+C select and copy the document's own text, never listing items.
Shift+Left and Shift+Right step over a whole grapheme cluster, such as an emoji with a skin-tone modifier. Right with a selection collapses it to its end. With the default key map, plain Left returns focus to the file listing. A click past the end of a wrapped line puts the caret at that display line's end. A Shift+click or double-click on a link selects its text; only a plain single click opens the link. Keyboard selection never changes the listing's selection. Smaller source previews use a native read-only text view with a caret and native keyboard text selection.
The header shows Find in preview only while the preview has searchable text. It sits after View source or View rendered and before Open in default application. Its tooltip reads "Find in preview (Ctrl+F)", or "Find in preview (/)" in 10xer mode, and toggling 10xer mode updates it. Click it, or press Ctrl+F (/ or keypad / in 10xer mode) while the preview owns focus, to search loaded source text or rendered prose and code. The find bar opens with its entry focused and the previous query selected. Search is literal and case-insensitive, and matches do not overlap: "aa" in "aaa" counts once. The query holds at most 256 characters.
The selected match is revealed and can be copied. The status reads "Match 1 of N" or "No matches", and is hidden while the query is empty. Enter and Next match, or Shift+Enter and Previous match, move between matches and wrap at either end; with zero matches both buttons are unavailable. An open find re-runs as an incrementally loaded source preview grows. Escape or Close find hides the bar and returns focus to the document without closing its preview; the selected match stays selected for Ctrl+C. The query follows Source and Rendered switching and survives reloading the same file. Previewing a different file, or closing the drawer, closes the find bar and clears the query.
Find does not read beyond the existing preview limits, search other files, or perform OCR. Rendered table cells, PDF pages, images, archives, and media are not searched. A Rendered view holding only tables shows no Find in preview button; textual tables can be searched in Source view. In 10xer mode, / in a preview with no searchable text returns the keys to the file listing and opens the listing's find prompt. Ctrl+F still filters filenames when the file listing owns focus, and in 10xer mode it keeps paging the preview.
Interactive tables
CSV and TSV use quote-aware parsing, preserve multiline fields, and tolerate ragged rows. The first row becomes column titles. Markdown and HTML tables share the same native ColumnView; HTML row headers remain styled cells when the first row is not entirely headers.
Tables open sorted ascending by the first column. Hover a column title for the pointer cursor, click to sort ascending or descending, and drag its divider to resize it. A compact up/down caret at the right of the header indicates the current direction. Standalone tables fill the preview's available height with a minimum height; tables embedded in prose retain their own bounded scrolling area. Sorting uses finite numeric values first, case-insensitive text next, and empty values last in ascending order; descending reverses that order. Sorting changes only the preview, never the file. Initial widths sample up to 64 rows, reserve enough room for compact fields, and give spare width to longer text. Every column, including the last, can be resized. Manual widths and sort order survive row recycling while that rendered view remains open.
Drag through cells and rows to select a continuous range in displayed sort order; dragging near an edge scrolls the table and preserves selection across recycled rows. Ctrl+C copies that range with tabs between cells and newlines between rows. A single click in any cell or empty space, or changing the sort, clears the selection. With a range selected, Ctrl+A, Ctrl+Shift+A, Escape, an arrow key, Home, or End also clears it; Ctrl+Alt+A leaves it. Native keyboard selection within a cell remains available. With focus on the table rather than a cell label, Ctrl+C copies all loaded rows in their current sorted order, with original full cell text and tab separators. Ctrl+Shift+C, Ctrl+Alt+C, and Ctrl+Super+C copy nothing from a focused table. With a non-Latin layout such as Russian, Ctrl+A in a focused cell selects that cell's text, and with no range selected Ctrl+C copies the cell's own selection, not the whole table. Cross-document selection also copies tables in their current order. Native sortable column titles are plain text; body cells retain supported inline styling and safe links.
Tables have no fixed row cap: a table over 200 rows or 512 cells renders in full. Markdown, HTML, and DOCX tables still count toward the 20,000-event and 4 MiB markup limits, so a table of a few thousand rows can exceed them (see Limits and fallback). Delimited and workbook output stops at 100,000 values, 4 MiB of cell text, or 256 columns, and a limited table shows "Table preview reached its text, column, or value budget; open the file to see all data." CSV/TSV retain the 1 MiB source-reading limit and Source fallback. Virtualization bounds resident row widgets; it does not make parsing or model memory unlimited.
Images, diagrams, and equations load asynchronously as rows are visited. Each preview renders at most 16 of them; every later image, diagram, or display equation shows "Preview limited to 16 images, diagrams, and equations" with its alt text or source, and a later inline equation shows its LaTeX source. Local images are limited to 8 MiB, Mermaid input to 16 KiB and 256 lines, equation input to 4 KiB, and decoded output to 800 × 800 pixels. Larger Mermaid blocks remain virtualized code. Media renderers run as per-request jobs inside the pooled preview supervisors (10-second CPU and bounded wall deadlines). That pool is separate from the file-list thumbnail pool, so a folder's thumbnail backlog does not delay a document's images, diagrams, or equations. Closing the preview cancels pending work. Missing files, unsupported formats, and decoder errors preserve alt text or diagram source without preventing the rest of the document from rendering.
Trust boundary
Document parsing and layout derivation run off the GTK thread through gio::spawn_blocking. The in-process, pure Rust parsers consume only the already bounded source string and produce escaped Pango markup. The layout boundary immediately decodes that reviewed markup into plain text and semantic spans before GTK receives it. Parser cancellation and preview request identity are checked before results are published.
Workbooks and Word documents are different: Calamine can allocate a complete worksheet before rows are extracted, and docx-rs decompresses every document part into memory. XLS/XLSX/ODS and DOCX parsing therefore runs in the preview sandbox, with a 20 MiB input-file limit, 2 GiB address-space limit, 10-second CPU limit, and 12-second wall deadline. Cancellation terminates the helper. The application validates bounded JSON cell or HTML output before parsing and deriving the shared document layout; DOCX HTML is generated by the helper, escaped, and reparsed by the same bounded HTML parser local .html files use. Compressed file size alone is not a decompression-memory limit.
This path does not use WebKit, Chromium, document script execution, or document CSS rendering. Document text parsers do not access files or the network. Markdown image references are opened atomically beneath the document directory, checked for regular-file type and size, then copied to private temporary inputs. Image decoding, Mermaid rendering, and equation rendering run in the existing resource-limited Bubblewrap sandbox, with no network or document-directory mount. Equations use a bundled, pinned MathJax program in QuickJS with no host bindings or module loader; user input is a string argument, never executable JavaScript. The JavaScript heap and stack are capped at 64 MiB and 1 MiB, with a two-second interrupt deadline. Only base and AMS TeX packages are registered; autoload, require, and HTML extensions are unavailable. No external TeX executable or npm installation is needed at runtime. See renderer build inputs. SVG subresource resolvers are disabled, including embedded images. Only validated bounded PNG output crosses back to GTK. Native GTK creates the final widgets; only a user-activated, revalidated http or https link can launch an external application.
System file chooser
Strata can serve the XDG Desktop Portal FileChooser interface for portal-aware applications. Native file pickers and applications that do not use the portal are unchanged.
The chooser is deliberately limited to local files and folders. It uses the main app's sidebar, Columns/Icons/List views, List type grouping, filters, metadata, previews, and themed controls. Recent appears when enabled in sidebar preferences and supported by the desktop's recent-files backend; only local targets are listed. Overwrite confirmation uses the same in-window modal as the app.
Strata handles Open, Save, and Save Files requests. A request without a title is titled “Open Files”, “Save File”, or “Save Files”, and one without an accept label uses Open or Save. Without a usable folder hint, the chooser starts in your Downloads folder (XDG_DOWNLOAD_DIR), or Home when that is undefined. A folder hint that is relative, inaccessible, or unanswered within 3 seconds falls back the same way. A Save suggestion naming a file that does not exist yet opens its folder with the full name in Name. A Save Files request lists the names being saved in a Files row instead of a Name field.
File-type filters and application choices share a row beneath the filename that wraps in narrow windows. Application choices appear as checkboxes and dropdowns, and the values you pick go back to the application. Options in the filter and choice dropdowns are radio items, and the selected one is reported as checked. A long filter list scrolls inside its dropdown, which opens toward the side of its button with more room. A request may carry any number of filters and rules. A request fails without opening a window when it would be the 17th open at once, reuses a request handle, carries a string over 4,096 bytes, offers more than 16 choices, or has a glob rule over 256 bytes or with more than 2 wildcard groups. When the application closes its request, the chooser closes.
File-open requests include a Name field. Type an existing filename in the current folder, or paste a direct http:// or https:// file URL, then click Open or press Enter. Typing a folder's name and pressing Enter opens that folder and clears Name. A name typed while the folder is still loading is kept when the first row is selected automatically. A name with no matching file shows “Choose an existing, accessible file”, and a file the selected filter rejects shows “The file does not match the selected filter”; the chooser stays open for another try.
A URL downloads to a temporary local file returned to the requesting application. A compact circular progress indicator and cancel button appear at the bottom-left of the action bar; downloads without a known size show a spinner and bytes downloaded. Escape or the cancel button stops the download and leaves the chooser open for another name or URL. A network or HTTP failure, such as a 404, shows “Could not download the file: …” with the error. A download the selected filter rejects shows “The file does not match the selected filter” and is not returned. Chooser validation errors, including Name-field file lookup and URL download failures, appear as plain error text in the action bar rather than adding a row above it. The address bar remains navigation-only, pasting with Ctrl+V never starts a download, and downloads are unavailable in folder and Save requests.
Downloads are named from Content-Disposition (filename*, then filename) or the last URL path segment, or download when neither gives a name. They persist under a strata-download-* folder in the temp directory after the chooser closes, so the requesting app can still open them. Folders older than a day are swept when the portal starts or a new download begins. URLs with credentials are not downloaded. A URL that answers with a redirect shows “The URL redirects elsewhere; paste the direct file URL instead”.
If a downloaded JPEG, BMP, single-frame GIF or static WebP has no canonical filename matching the selected filter, but PNG would match, Strata validates the image in its sandbox and asks “Convert image to PNG?” with Convert to PNG / Cancel. Detection uses file contents, not the URL extension or HTTP content type. BMP detection requires BM, zero reserved bytes in its file header and a known DIB header size (12, 40, 52, 56, 108 or 124 bytes); BM alone is not enough.
When the bytes sniff as a JPEG, BMP, GIF, WebP or PNG image and the name lacks that format's extension, but the name with it (such as .jpg for JPEG bytes) passes the selected filter, Strata renames the download to that extension and returns it without asking, checking or converting. This extension repair runs even when the original name already passed the filter; a failed rename shows “Could not name the downloaded image: …”. If neither that kind's canonical name nor a PNG name matches, the normal filename filter still judges the download: it can be returned under its original server-provided name, such as JPEG bytes named attachment.pdf with a *.pdf filter. A .png name alone does not satisfy a PNG-only filter: JPEG, BMP, static WebP and single-frame GIF bytes still offer conversion. Under a filter that accepts PNG but not JPEG, a .png download whose bytes are not a supported image shows “This download is not a supported image. Choose a JPEG, BMP, static WebP, GIF or PNG image.” Bytes sniffed as PNG that the selected filter accepts under a PNG name open without conversion or sandbox validation, after any filename repair; that includes APNG and corrupt PNG data with a PNG signature.
Conversion preserves full resolution, transparency, orientation and compatible embedded colour profiles. An animated GIF or WebP shows “Animated images cannot be converted to PNG. Choose a static image instead.” during the check, without the conversion prompt. Other conversion inputs (including TIFF, SVG, AVIF and HEIC) are unsupported. An embedded ICC profile recognized by its acsp signature must have a colour space matching the decoded image, or conversion aborts. This intentionally rejects grayscale JPEGs carrying RGB profiles and CMYK profiles even when the JPEG decoder has emitted RGB pixels. An unprofiled CMYK JPEG skips that check and can be converted using the decoder's RGB output; Strata does not add colour conversion or strip incompatible profiles.
Image processing is cancellable and limited to 32 MiB input, 16 megapixels, 16,384 pixels per edge and the sandbox's memory/CPU/time limits. The separate 32 MiB encoded PNG output cap also applies: 16 megapixels of RGBA exceeds 32 MiB before compression, so an image within the pixel cap can still fail with “The converted PNG exceeds the 32 MiB output limit”. Either cap can reject conversion. The decoder's 128 MiB allocation budget is best-effort, not a hard memory bound; pre-decode dimensions and sandbox process limits provide the resource boundary.
Cancel, Escape, or a conversion failure leaves the chooser open without returning the incompatible original. Clicking Open again on the same URL reuses the downloaded file while it still exists. Changing the name or selected filter during the check, the conversion prompt, or the conversion stops the job and shows “The name or filter changed. Press Open to try again.” After successful conversion, both the cached original and the returned PNG remain in their temporary folders until the one-day sweep; closing the chooser does not remove either file.
Folder-only requests hide regular files in both directory listings and recursive results. File requests keep folders available for navigation. Changing a file-type filter refreshes the current results without clearing the search query; selection and acceptance follow the new filter. Local drives mounted before the chooser opened appear under DEVICES in its sidebar once the dialog has painted; network shares do not.
File Open requests show an Open files read-only checkbox; checking it tells the application to open the returned files read-only. In a single-selection request, selecting another item replaces the selection, including with Ctrl or Shift clicks and across grouped List sections, so Open returns one item. In Columns, a filter result selected in a column other than the active one is returned on Open. In a folder request, accepting while only the automatically selected first row is selected returns the displayed folder; an explicitly selected child folder returns that child.
In Save dialogs, selecting a file copies its name into the name input without accepting the dialog. Names that are not valid UTF-8 display with replacement characters, but Save still targets the selected file's exact name while the name input shows it unchanged. Edited name text is saved literally, replacement characters included; retyping the exact displayed text targets the original file again. The automatic initial selection does not change the suggested name or destination. Selecting a folder changes the destination without changing the name or navigating into it. In Recent, select a file to save in its containing folder, or navigate to a local folder first. Saving over an existing file asks “Replace existing file?” (“Replace existing files?” for several) with Cancel focused; Cancel keeps the chooser open and Replace returns the path. Saving where a folder of the same name exists fails with “A folder named “name” already exists”.
Resizing a Miller column or a List heading in the chooser saves that width as the chooser default, so the next request opens with it. Dragging or double-clicking a Miller column edge stops at the dialog's file area beside the sidebar, and a saved width wider than that area opens narrowed to it. Regular Strata windows also remember widths, using separate browser defaults.
A Wayland application's exported parent handle makes the chooser a transient dialog of that application's window. X11 parent handles are ignored, and those requests open as standalone windows.
Destination choosers
The same chooser window serves Strata's own Move to…, Copy to…, Extract to…, and Send to… → device → Choose folder… commands. It opens as a floating modal folder chooser over the window the command came from. Invoking another destination command while one is open brings the existing chooser forward instead of opening a second. Closing the originating window closes its chooser, and Cancel leaves the files and the window's location unchanged.
Move to, Copy to, and Extract to offer New Folder. Enter in the path entry navigates there; Ctrl+Enter in the file list or the action button confirms the displayed folder, or a child folder you explicitly selected. For Send to, the sidebar and its toggle are hidden, and Ctrl+B (Ctrl+N in 10xer mode) and Ctrl+Shift+B leave them hidden. Send to also disables New Folder in the menu, the toolbar, and Ctrl+Shift+N. Navigating outside the device shows “Choose an existing folder inside this removable device.”
Initial size
The chooser opens at 80% of its bound's width and 78% of its height, leaving at least 120 px and 100 px. The result is clamped between 640×460 and 1000×680 px. On a bound under 760 px wide or 560 px tall, the 640×460 minimum overrides that clearance; a bound smaller than 640×460 caps the minimum at the bound. The bound is the monitor. With a parent size it is the smaller of the monitor and the parent in each dimension, or the parent alone when monitor geometry is unavailable. With neither, the chooser opens at 920×580. Destination choosers use their originating window's current size as the parent size on any compositor. Moving the chooser to another monitor keeps a manual resize.
Initial size in split-window layouts
On Hyprland, requests with a Wayland parent and an application ID can use the requesting application's window size as an initial sizing hint. Strata queries Hyprland's local IPC socket before loading the requested directory, and uses the hint only when exactly one window's current or initial class matches the app ID (case-insensitively). A sole matching window that is unmapped, hidden, or zero-sized gives no hint. The query is read-only, limited to 100 ms and a 1 MiB reply, and does not depend on which window has keyboard focus. Monitor dimensions still cap the result.
The exported Wayland handle does not expose parent geometry. Other compositors, X11 requests, missing or differently named app IDs, multiple matching windows, and unavailable IPC retain monitor-based sizing. This is a best-effort improvement, not guaranteed parent-relative sizing on every desktop. GTK's compositor bounds and the controls' minimum usable size continue to apply.
Initial placement on Hyprland
On native Wayland under Hyprland, floating choosers open at the center of their
monitor by default, rather than at the center of the calling application. The portal process identifies its
windows as io.github.lgse.Strata.FileChooser, separate from the normal file
manager's io.github.lgse.Strata identity.
Before showing a chooser, Strata registers the named runtime rule
strata-file-chooser-center through Hyprland's IPC socket. The rule matches only
the chooser identity and sets center; it does not force floating, resize the
window, or remove its parent/modal relationship. No Hyprland configuration files
are edited. The same rule is refreshed before each chooser, so it also works
after a compositor configuration reload without accumulating rules.
Both Lua and legacy configurations with named window-rule support are handled. The entire placement request has a 100 ms deadline; unsupported rules, unavailable IPC, and other compositors retain compositor-default placement. Centering does not require identifying the calling application's size. Destination choosers register the same rule and use the chooser identity, so they open centered too. Regular Strata windows keep their usual placement.
Opt in through the app or installer
Strata never replaces your Open and Save dialogs on its own. Nothing changes
without consent. Enable it in Settings → General → System file manager,
during installation, or with strata --install-portal.
The Settings row sets the file chooser together with folder opening and Reveal in
File Manager. The installer and the --install-portal and --uninstall-portal
commands change only the file chooser; the installer asks about folder handling
in its own questions.
The installer asks about the file chooser separately, defaulting to No, after
placing the binary at its permanent path. For unattended installation,
--with-file-chooser opts in and --without-file-chooser keeps your current
chooser. Either flag implies --non-interactive, so the installer asks nothing
and declines every integration you do not name. A plain --non-interactive
install also leaves the chooser unchanged.
--with-file-chooser fails on a release without portal support.
A declined installer question or --without-file-chooser runs
strata --dismiss-portal-prompt. That command only creates
${XDG_CONFIG_HOME:-~/.config}/strata/portal-opt-in-v1 and leaves portal
preferences unchanged; Strata itself never asks on launch, whether or not the file
exists.
System file manager in Settings
Settings → General → System file manager lists Open and Save dialogs, Opening folders, and Reveal in File Manager, each marked configured or not. On Omarchy it also lists Keyboard shortcuts; elsewhere that line is hidden. Close open file dialogs before changing setup.
Complete setup installs the file chooser portal, makes Strata
(io.github.lgse.Strata.desktop) the inode/directory handler, and installs the
per-user FileManager1 service used by Reveal in File Manager. It is hidden once
every line is configured. It fails with “Another per-user FileManager1 provider is
already installed: …”, followed by the conflicting service file's path, when
another user service already owns that name.
On Omarchy 3 or 4, Complete setup also binds Super+Shift+F and
Super+Alt+Shift+F to Strata in $XDG_CONFIG_HOME/hypr/bindings.conf, or
bindings.lua on Omarchy 4. Each change to the bindings file first keeps a
strata-keybind-backup- copy of the previous file beside it, or beside the link
when the bindings file is a symlink. If Hyprland's hyprctl configerrors then
reports errors, the previous file is restored and the error names the backup.
A user-owned symlinked bindings file is written through the link, which stays a
link, including during that rollback. An existing bindings file keeps its
permission bits, so a 0644 file stays 0644. With a dangling link, Complete
setup fails with an error naming the missing target and does not create it. The
steps that ran first still apply: the file chooser, the folder handler, and the
FileManager1 service are installed, and an empty strata-keybind-backup- file is
left beside the link. A link,
or a target reached through one, owned by another user makes Complete setup
and Restore default fail and leaves the target unchanged.
Restore default appears while any part is installed. It removes the
FileManager1 service and the file chooser portal. It returns inode/directory to
the handler recorded at setup, or to Nautilus when none was recorded, and leaves it
alone when it no longer points to Strata. With no recorded handler and no Nautilus,
it fails with “No previous folder handler was recorded and Nautilus was not
detected. Choose another default file manager first, then retry Restore default.”
On Omarchy, Restore default replaces the Strata shortcut block with
nautilus --new-window bindings. When Nautilus is not detected, it fails with
“Nautilus was not detected; the Strata keyboard shortcuts were left unchanged.”
In that case, and when the shortcut block fails the checks below, the folder
handler step has already run, but the shortcuts, the FileManager1 service, and the
file chooser portal stay installed until you fix the cause and run Restore
default again. With a dangling bindings link, it leaves the shortcuts and the
link unchanged.
A hand-edited Strata shortcut block shows Keyboard shortcuts as not configured, and both Complete setup and Restore default fail with “The Strata keyboard shortcuts have been customized; restore them manually to avoid losing your edits.” A start marker without an end marker, or the reverse, or a repeated marker makes them fail with “The Strata keyboard shortcut block is ambiguous; restore it manually.”, and an end marker before the start with “The Strata keyboard shortcut block is malformed; restore it manually.” Complete setup leaves the bindings file unchanged in each case, but the steps that ran first still apply, as with a dangling link.
Per-user installation
Ensure xdg-desktop-portal is installed. The Arch/Omarchy installer includes it
when file chooser integration is selected. Close active file dialogs before
enabling or restoring the chooser: setup restarts the portal frontend.
Install Strata at a stable absolute path, then run:
strata --install-portal
This installs the portal metadata and D-Bus activation service below $XDG_DATA_HOME, makes Strata the preferred FileChooser while retaining the active backends as fallbacks, stops any running Strata chooser backend, reloads D-Bus, and restarts the portal frontend. If no user portal configuration exists, Strata copies the active desktop configuration before changing the FileChooser preference. The command records whether that user override was created or modified so it can be removed safely later.
The chooser backend is activated on demand and exits after about two minutes without an active request (checked every 10 seconds). An open dialog (including a pending request) keeps it running; closing the last dialog starts the idle countdown again. When Strata is the configured file chooser, an in-app update restarts the portal services so the next dialog runs the new binary. In-app updates also stop your other Strata windows and strata --portal chooser processes running the old binary from the same install path: they receive SIGTERM, then SIGKILL after 5 seconds. Processes started with other flags, such as preview helpers or a strata --gapplication-service instance started by Reveal in File Manager, other users' processes, and Strata binaries from other install paths keep running. Strata then relaunches the updating window with the replacement binary.
External package-manager updates and manual binary replacements do not run that retirement step. The next time you launch Strata, it restarts the portal services if a running strata --portal from the same install path was started from the replaced executable. Other old Strata windows keep running until you close them or log out.
If a stop, reload, or restart step fails, --install-portal and --uninstall-portal print “Could not reload every portal service. Ensure xdg-desktop-portal is installed, then log out and back in before testing.”
The generated D-Bus service contains the absolute path of the command being run. Move Strata to its permanent location before installing the portal. For safe activation, every component of the canonical executable path must be owned by the current user or root and must not be group- or world-writable. D-Bus service-file argument parsing is not shell quoting, so the installer also rejects executable paths containing whitespace, quotes, or backslashes.
Manual installation
Run the equivalent commands below from the extracted release archive. They use the default XDG locations and an existing installation at ~/.local/bin/strata:
data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
strata_executable="$(readlink -f "$HOME/.local/bin/strata")"
strata_replacement="${strata_executable//\\/\\\\}"
strata_replacement="${strata_replacement//&/\\&}"
strata_replacement="${strata_replacement//|/\\|}"
install -d "$data_home/xdg-desktop-portal/portals" \
"$data_home/dbus-1/services" \
"$config_home/xdg-desktop-portal"
install -m 644 portal/strata.portal \
"$data_home/xdg-desktop-portal/portals/strata.portal"
sed "s|@STRATA_EXECUTABLE@|$strata_replacement|" \
portal/org.freedesktop.impl.portal.desktop.strata.service.in \
> "$data_home/dbus-1/services/org.freedesktop.impl.portal.desktop.strata.service"
chmod 644 "$data_home/dbus-1/services/org.freedesktop.impl.portal.desktop.strata.service"
gdbus call --session \
--dest org.freedesktop.DBus \
--object-path /org/freedesktop/DBus \
--method org.freedesktop.DBus.ReloadConfig
The generated D-Bus service must contain an absolute Exec= path. If that path contains whitespace, quotes, or backslashes, install Strata somewhere else; D-Bus service-file argument parsing is not shell quoting.
Edit the portal configuration the frontend uses for your desktop, as strata --install-portal does. In $config_home/xdg-desktop-portal/, that is the first existing <desktop>-portals.conf for a lowercased name in XDG_CURRENT_DESKTOP, such as hyprland-portals.conf, otherwise portals.conf. If neither exists there, copy the active desktop configuration into that directory, keeping its file name: the first such file in the system directories, usually /etc/xdg/xdg-desktop-portal/ or /usr/share/xdg-desktop-portal/. Create portals.conf only when no configuration exists anywhere. A user file outranks the system one, so a file holding only the FileChooser line would drop the desktop's other preferences. Preserve the file's existing [preferred] section and settings, and merge Strata into the FileChooser preference:
[preferred]
org.freedesktop.impl.portal.FileChooser=strata;<existing-backend>;
Replace <existing-backend> with the backend already configured for the desktop, such as gtk or gnome. Do not install the placeholder literally and do not replace unrelated portal preferences. The archive's portal/portals.conf is an example, not a complete desktop configuration.
Restart the frontend so it rereads portal metadata and preferences:
systemctl --user restart xdg-desktop-portal.service
On a desktop that does not manage the frontend as a systemd user unit, log out and back in instead.
Keyboard navigation
- File selection fills, keyboard cursor outlines, and pointer-hover suppression use the main app's shared input-ownership styling, including when switching back to keyboard navigation after using the mouse.
- With 10xer mode off, file-open and single-file Save dialogs start with visible focus in Name; Save selects the suggested filename. Folder and Save Files requests start on the sidebar toggle. If focus is lost, an arrow returns it to the same place without a click.
- Tab/Shift+Tab traverse controls; arrows move between toolbar icons and options. The file list is a single Tab stop (the whole strip in Columns), and Tab into it lands on the keyboard cursor.
- Up from the first file row reaches the pane toolbar; Down returns to files. With Keep arrows in file list on in Settings → General, arrows stay in the file list: use Tab or Shift+Tab to reach the toolbar and Ctrl+Shift+B to reach the sidebar. In 10xer mode, arrows also stay in the file list.
- Icons arrows follow the visual rows and columns. List arrows follow the displayed order, including type grouping. Shift+arrows extend or shrink a range across groups; plain arrows select only the focused item.
- Space/Enter activate focused buttons and toggles. Down or Enter opens a focused dropdown; its arrows and Enter select an option.
- Enter or Shift+Enter on a focused file accepts the request. In a multiple-selection request with files selected, it returns every selected file, the same as Open, even when the focused file is outside the selection. With a folder and files selected, it returns only the files. Enter on a folder opens it, even with files selected.
- Ctrl+1, Ctrl+2, and Ctrl+3 switch to Columns, Icons, and List. F5 refreshes; Ctrl+H or Ctrl+. toggles hidden files. Ctrl+A in the file list selects all only in multiple-selection requests.
- With Type to search on (the default) and the file view focused, typing a
printable character opens the filter seeded with it;
/opens an empty filter. - Ctrl+click moves focus to the item it toggled, so the preview follows it. Dragging from blank space draws a marquee only in multiple-selection requests. A blank click in the file list or sidebar clears the selection in every request. A plain click on blank space in a preview that is showing something keeps the selection; in multiple-selection requests, dragging from it into the file list starts a marquee.
- With folders set to open on a single click, a single click on a folder in Icons or List opens it, and a single click on a file only selects it. With single-click previews on, clicking a previewable file opens the shared preview pane.
- Dragging a Miller column's right edge resizes it; double-clicking the edge fits it to its content.
- F2 renames a single selected file or folder. The editor opens with a file's
name before its last
.selected, and a folder's whole name selected. Escape cancels the name editor without closing the chooser. Right-click an item for Rename, Properties, Compress… (local items), Move to Trash and Permanently delete (where the location allows them), and Quick preview for one previewable file; right-click empty pane space for New Folder. Alt+Enter opens Properties from the file list. Properties preserves multi-selection, while Rename is disabled for multiple selected items. - With the file view focused, Delete moves the selection to Trash and Shift+Delete asks to delete permanently. Where the open folder has no Trash but allows deletion, Delete asks to delete permanently and explains why.
- Text fields keep their cursor keys and Ctrl+A; Ctrl+A in the filename entry selects its text, not files. Ctrl+L edits the location; Ctrl+F opens the pane filter.
- Ctrl+Shift+N or the New Folder button beside Refresh creates
new folder(or the first freenew folder (1),new folder (2), and so on) and selects its name for editing. Enter or clicking away commits a valid name. Escape or an empty or invalid name keeps the default name, and the folder stays. - Ctrl+B (Ctrl+N in 10xer mode) or the sidebar toggle in the top bar shows or hides the sidebar. Unless arrows are kept in the file list, Left from the outer file-list edge or a leftmost Icons cell focuses the visible sidebar. Ctrl+Shift+B also focuses it, first showing the sidebar if it is hidden; in 10xer mode it does nothing while the sidebar is hidden. Right returns to files without changing selection. Up from the first sidebar row reaches the sidebar toggle.
- Space on a file toggles preview. In a folder-selection request, Ctrl+Enter in the file list accepts the same as Open: it returns the displayed folder, or a child folder you explicitly selected.
- Escape dismisses the innermost menu, dropdown, inline edit, filter, location edit, preview, download, or confirmation before cancelling the request. Escape on a focused filter result dismisses the filter and keeps the request open. The Replace prompt, the image conversion prompt, and the delete confirmation for a folder without Trash initially focus Cancel. The Shift+Delete “Permanently delete …?” confirmation initially focuses its delete button.
With 10xer mode on
- With 10xer mode on, the chooser follows the saved preference and live changes to it, and uses that keymap and footer within the request's limits. The pane chrome hides; Accept, Cancel, the close button, and List headings stay. The sidebar toggle's tooltip names Ctrl+N. Turning the mode off restores the chooser's own keys.
- Every request starts with focus in the files. Enter or
oon a file chooses it; in a multiple-file request with a fill, they choose the fill. Enter oroon a folder opens it. The request takes the fill, or the cursor item when nothing is filled; the automatic first-row selection never counts. - Escape takes one dismissal step (prompt, filter, search, find, range, preview,
fill) and then cancels the request.
qneither ends the request nor leaves the mode; Ctrl+Shift+M leaves the mode with the request still open. - F1 shows a reference listing only the keys the request allows; Escape closes
it without cancelling. The
gpanel leaves outg t,g n,g +, andg −, andtdoes not start a tab chord.fandshits follow the request's folder-only and file-type limits. - Tab moves from the files to the header, then to Name when the request has one, then back to the files. While Name or the location field has focus, every key is typed except F1, Ctrl+Shift+M, and Escape. Escape in Name returns to the files and keeps the edit; Escape in the location field cancels the edit and returns to the files.
- In a Save request, Enter in the files saves the name in the current folder,
whatever the cursor is on; moving the cursor changes neither the name nor the
folder. In a single-file Save request,
ror F2 edits Name with the part before the extension selected, andoon a file saves over it after a Replace prompt with Cancel focused. Beside Cancel and Save, a single-file Save request shows Enter,r, andohints; a Save Files request shows only the Enter “Save here” hint. y,x,p,P,Y,X,M,C,R,O,;,i,g +,g −,Q, Ctrl+C, Ctrl+X, and Ctrl+V flash “Not available in the file chooser”. In a single-item request, Space,v,V, Ctrl+A, and Ctrl+R flash “Only one item can be chosen”.g t,g n, and remote pins flash “Only local folders can be opened here”.a,d,D, sort chords,.,c c, andc nwork as in a window, and so dorand F2 outside single-file Save requests.
Verification
Confirm that D-Bus can activate Strata and that it advertises FileChooser version 4:
gdbus introspect --session \
--dest org.freedesktop.impl.portal.desktop.strata \
--object-path /org/freedesktop/portal/desktop
gdbus call --session \
--dest org.freedesktop.impl.portal.desktop.strata \
--object-path /org/freedesktop/portal/desktop \
--method org.freedesktop.DBus.Properties.Get \
org.freedesktop.impl.portal.FileChooser version
The second command should report uint32 4. Then open or save a file from a portal-aware application. Only local locations appear in the picker; entering a remote URI in the address bar shows “The system file chooser supports local files and folders only.” File-open requests accept direct http(s) URLs through the Name field.
Portal backend selection happens before a request is sent. Keeping the existing backend after strata; lets the frontend choose it when Strata's .portal metadata is absent. It does not provide live failover if an already-selected Strata backend crashes during a request.
Uninstall
Run the matching per-user command:
strata --uninstall-portal
It removes Strata's metadata and activation service and restores the previous user portal configuration. If the configuration changed after installation, it preserves those changes and removes only Strata from the FileChooser preference. It then stops any running Strata chooser backend, reloads D-Bus, and restarts the portal frontend. If the frontend cannot be restarted automatically, log out and back in.
For a complete Strata uninstall, also remove the application binary and desktop entry as described in Update or uninstall.
Manual uninstall
Remove the Strata metadata and activation service:
data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
rm -f "$data_home/xdg-desktop-portal/portals/strata.portal" \
"$data_home/dbus-1/services/org.freedesktop.impl.portal.desktop.strata.service" \
"$data_home/strata/portal-install/state.toml"
rmdir "$data_home/strata/portal-install" 2>/dev/null || true
gdbus call --session \
--dest org.freedesktop.DBus \
--object-path /org/freedesktop/DBus \
--method org.freedesktop.DBus.ReloadConfig
strata --install-portal edits the user configuration named after your desktop, such as hyprland-portals.conf on Hyprland, and portals.conf only when no desktop-specific file applies. Edit each portals.conf or <desktop>-portals.conf file in ${XDG_CONFIG_HOME:-$HOME/.config}/xdg-desktop-portal/ that lists strata, remove strata; from the FileChooser preference, and keep the previous backend. If that file did not exist before you installed the portal, delete it instead. Then restart the portal:
systemctl --user restart xdg-desktop-portal.service
SFTP locations
Strata reaches sftp:// locations through GIO/GVfs, the same URI-native path it
uses for every other remote scheme. This page covers what the client supports.
Addresses
Press Ctrl+L, type an address, and press Enter.
| Address | Meaning |
|---|---|
sftp://host/path | Connect as the local user on port 22 |
sftp://user@host/path | Connect as user |
sftp://user@host:2222/path | Connect as user on port 2222 |
A password typed in the address, such as sftp://alice:secret@host/path or
sftp://alice;password=secret@host/path, is taken out of the address before
Strata connects. The location bar returns to the breadcrumbs while it connects.
The password is used for that one connection attempt and never saved. If it is
rejected, the normal sign-in dialog opens.
SCP-style addresses such as user@host:path, and UNC paths such as
\\host\share or //host/share, are refused with "UNC paths
(\\host\share) and SCP-style addresses (user@host:path) aren't supported.
Use a URI instead, such as smb://host/share, sftp://host/path, ftp://host/path,
or dav://host/path."
A scheme Strata does not handle, such as ssh://host or scp://host, is
refused with "The ssh:// scheme isn't supported. Use an absolute local path or
one of: smb://, sftp://, ftp://, ftps://, dav://, davs://, or recent:///."
Schemes match regardless of case, so SFTP://host/path works. A refused address
opens an Unable to open location dialog, and the location bar returns to
the current location.
Browsing an SFTP location
Opening an sftp:// address mounts it first if needed, then opens it. Entries
keep their sftp:// address; Strata never shows the /run/user/$UID/gvfs/…
FUSE path.
The location field and Properties show non-ASCII characters decoded, such as
sftp://host/café, when the whole path is valid UTF-8 and contains no %2F.
Spaces and other reserved characters stay percent-encoded, such as
sftp://host/My%20Share. Otherwise the whole path shows percent-encoded, such
as sftp://host/share/%FF%20name. Column headings, peek headings, and window
titles show percent-decoded names. Files whose names are not valid UTF-8 are
still listed. An entry whose address Strata cannot convert is left out of the
listing.
A large folder fills in progressively. Loading finishes only after every row
read so far is shown. A load stops after 100,000 entries or 10 seconds. A
warning icon beside the folder's heading then marks a partial listing: "This
directory has more entries than could be loaded; showing a partial listing."
A folder you open by typing a non-ASCII address, such as sftp://host/café x,
still refreshes when an entry is created or deleted in it. If you leave a folder before it finishes loading, its remaining
rows never appear in the folder you moved to or in columns that were closed.
Breadcrumbs, history, column descent, and hover peek work as they do on local
folders. You can copy a remote file, drag it out, or open it in its
default application.
Ejecting or unmounting the SFTP mount from its DEVICES row while you browse inside it returns the browser to Home.
Authentication
The SFTP backend decides which credentials it needs and asks Strata for them:
- Password — the backend requests a username and password. Strata shows Authentication required with only the fields the backend asked for, and a Connect button. SMB's domain and anonymous options do not appear on an SFTP prompt. If the backend can save passwords, the dialog also offers Password storage: Don't remember (the default), Until logout, or Forever. Strata itself stores nothing; the backend and your keyring keep the password.
- SSH key — the agent or an unencrypted key answers without any prompt.
- Encrypted key —
ssh-addcan unlock it in your agent before connecting. If GVfs asks Strata for the key's passphrase, the dialog is titled Passphrase required and its field is labelled Passphrase. Not every GVfs/OpenSSH configuration sends a key-passphrase request to Strata.
Wrong credentials reopen the dialog with "Those credentials weren’t accepted. Check … and try again." The message names only the fields the dialog shows, such as "Check username, password and try again." or, on a key prompt, "Check passphrase and try again." If the prompt has no fields to name, it says "That attempt wasn’t accepted. Try again." Cancel or Escape returns to the previous location with no error dialog and no history entry.
Host keys
An unrecognized or changed host key opens Verify server identity. It shows the backend's question and every choice the backend offers, and Strata never answers it for you. The dialog warns: "Only continue after verifying the SSH host key through a trusted source." and "If the server did not provide a fingerprint, verify it outside Strata before continuing."
The backend may not supply a fingerprint (it can report ???); verify the
server's SSH host key through a trusted channel before choosing to continue.
The rejecting choice, such as Cancel, comes first and has focus. Declining with
that choice, Escape, or the close button returns to the previous location with
no sign-in dialog and no error.
A changed key may indicate interception; verify it with the server administrator before accepting. Depending on your GVfs and OpenSSH setup, a changed key can instead fail at once with the host-key message under Failures. Verify the new fingerprint before you reconnect.
Failures
Each failure has its own message. If the sftp backend isn't installed, opening
an sftp:// address shows Unable to open location with: "The sftp://
backend isn't installed. Install your distribution's GVfs sftp backend,
commonly packaged as gvfs or gvfs-backends, then try again."
A failure while connecting shows it in an Unable to connect dialog:
| Failure | Message |
|---|---|
| Host not found | "That host couldn’t be found. Check the address and DNS settings." |
| Connection refused | "The host refused the connection. Check the service and port." |
| Timeout | "The connection timed out. Check the host and firewall." |
| Host or network unreachable | "That host is unreachable. Check your network connection." |
| Host key rejected | "The remote computer’s host key could not be verified. Confirm its fingerprint with the server administrator before trying again." |
A host-key failure never reopens the sign-in dialog. When a connection or folder load fails with other backend text, or the backend asks about a host key, any address in that text is shown with its user info, query, and fragment removed.
At the default log level, connecting to and listing a remote location never
logs its host, path, username, or password. A mount logs only the backend name,
the mount strategy, and the outcome, with the error domain and code on failure.
A folder load logs a request id, the backend name, entry counts, and elapsed
times, plus the error domain and code or the reason when it fails or stops
early. An entry left out of a listing logs a warning with only the request id
and backend name. Run with RUST_LOG=strata=debug to log locations, including
the folder and name of a left-out entry. Even then, URIs omit user info,
authentication parameters, query, and fragment.
At startup Strata checks that GVfs (gvfsd) answers within 2 seconds. If it
does not, Strata prints "GVFS is unresponsive; using local filesystem and
volume support for this session." to standard error and the window still opens,
with local file and volume support only. sftp:// and other remote addresses
cannot open until you restart Strata with a working GVfs session.
Signed updates
Strata authenticates in-place updates in process. Users need neither the GitHub CLI nor a GitHub account, token, keyring, OpenSSL command, or signing tool. Package-managed installations still use their package manager.
Trust and format
data/update-keys.json is the trust store compiled into Strata. It contains raw
32-byte Ed25519 public keys encoded as lowercase hexadecimal. Private keys must
never enter the repository or a release artifact. A key ID is the lowercase
SHA-256 of the raw public key, not of its textual encoding.
Every release since signed updates were introduced (v1.0.0, and the v0.22.0 prereleases before it) publishes these two files alongside its archives:
strata-update-manifest.jsonstrata-update-manifest.signatures.json
The manifest is UTF-8 JSON with exactly these fields:
{
"schema": 1,
"repository": "lgse/strata",
"tag": "v0.12.0",
"source_commit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"artifacts": [
{
"name": "strata-0.12.0-x86_64-unknown-linux-gnu.tar.gz",
"target": "x86_64-unknown-linux-gnu",
"size": 123456,
"sha256": "<64 lowercase hexadecimal characters>"
}
]
}
The example values are illustrative, not a usable release. The publisher must
include both x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu. The
consumer accepts at most one artifact per supported target, so two in total, and
verifies the selected architecture and exact asset name. Each artifact must be
named strata-<version>-<target>.tar.gz, with a nonzero size of at most 128 MiB.
A manifest with a missing, extra, or wrongly typed field fails with "Invalid
signed update manifest: <reason>". A manifest with another schema, repository,
or tag, a source_commit that is not 40 lowercase hex characters, or an empty
or over-eight-entry artifacts list fails with "The signed manifest does not
identify the selected Strata release". An unknown target, a duplicate name or
target, a misnamed entry, a zero or oversized size, or a sha256 that is not 64
lowercase hex characters fails with "The signed manifest contains invalid or
duplicate artifacts". A manifest without this machine's architecture fails with
"The signed manifest does not contain this architecture's update". Files inside the
archive may evolve; the package directory, executable, and SOURCE_COMMIT remain
required. Release archives use tar --format=ustar so long prerelease portal
paths do not introduce GNU/PAX extension records, which the bounded extractor
rejects.
The signature envelope has schema: 1 and a signatures array of one to eight
entries. Each entry has only key_id (64 lowercase hex characters) and
signature (128 hex characters). An envelope with a missing, extra, or wrongly
typed field fails with "Invalid update signatures: <reason>". Any other schema
or entry count fails with "Unsupported update signature format".
The Ed25519 message is the bytes strata-update-manifest-v1, one NUL byte, then
the exact published manifest bytes, including its trailing newline. Readers
must not reserialize the JSON before checking the signature. At least one
signature from an embedded key must verify, or the update fails with "No
trusted release key signed this update manifest". Unknown keys do not confer
trust; multiple signatures allow old and new clients to coexist during rotation.
Manifests are signed in a release job that runs only after both builds succeed and needs a maintainer's approval. It runs signing tools from the workflow's own commit, never from the selected prerelease source. A missing signing key, or one Strata's trust store does not list, stops publication.
Download and verification
A release whose tag or archive name does not match its version is refused first,
with "The release names an unexpected update artifact." Strata downloads the
archive only from
https://github.com/lgse/strata/releases/download/<tag>/strata-<version>-<arch>-unknown-linux-gnu.tar.gz.
Any other location is refused with "The release points at an unexpected
download location."
The client bounds manifest/signature downloads to 32 KiB/8 KiB respectively, including bodies without Content-Length. Metadata over its limit fails with "The signed update metadata is too large". A release without a manifest fails with "This release has no signed update manifest. Choose a newer release or download it manually." While Strata fetches and checks the signed manifest, the Updates row and the update dialog read "Verifying update…". They read it again after the download, while the archive is checked.
Strata authenticates metadata before requesting the archive, caps the archive at
its signed size (at most 128 MiB), and verifies its SHA-256 in Rust before
extraction or execution. An archive that exceeds its signed size stops with "The
update is larger than expected and was not installed". The signed tag,
repository, architecture, package name, and source commit must match the requested
release and package. An archive whose size or SHA-256 differs from the signed
values fails with "The update does not match its signed size and checksum". An
archive whose package directory is not the selected one fails with "The
authenticated archive does not contain the selected release package". A
packaged SOURCE_COMMIT that differs fails with "The packaged source commit
does not match the signed manifest". No separately downloaded checksum or mutable API lookup is
an authentication authority. Stable releases sign the original build source SHA,
not the subsequent version-bump commit; previews sign their selected source SHA.
Each download, the signed metadata included, fails after 30 seconds without a connection or 30 seconds without receiving any bytes, the wait for the server's first reply included. Sending the request and receiving the response headers must also each finish within 60 seconds. There is no limit on total download time, so a slow download that keeps receiving bytes finishes.
When the archive download times out while looking up or connecting to the server, or while sending the request, it reads "Could not reach the download server — check your connection and try again". When it times out waiting for the response or for data, it reads "The download stalled — check your connection and try again". Other network errors, such as a refused connection or a failed name lookup, read "Could not download the update: <reason>". A metadata request that fails before its response arrives, a timeout included, reads "Could not download signed update metadata: <reason>". Once the metadata response has started, its errors read as for the archive.
Extraction, probe, and rollback
Strata extracts the archive itself. It rejects an archive containing symbolic or
hard links, device files, named pipes, GNU or PAX extension records, absolute
paths or .. components, more than 512 entries, more than one top-level
directory, a file over 256 MiB, or more than 512 MiB of extracted data. The
extracted package directory must match the selected asset name and contain
strata and SOURCE_COMMIT.
Before installing, Strata runs the extracted binary headless with
--gvfs-probe. If the probe exits with an error, the update fails with "The
downloaded update does not run on this system". If it runs longer than 2
seconds, it fails with "Update verification timed out". The previous binary is
kept beside the new one as .strata-update-rollback. If the installed binary
fails the same probe, Strata restores the previous binary and the update fails;
the running Strata is not relaunched. If the relaunched binary exits with an
error within 20 seconds, Strata restores the previous binary and launches it. Strata deletes
the preserved copy 60 seconds after it starts.
Malformed, unsigned, oversized, or mismatched updates are refused without
replacing the installed binary. GitHub's build-provenance attestations and
.sha256 files remain published for independent verification and packaging, but
are not prerequisites or fallbacks for this client protocol.
Rotation and compromise
A release may be signed by several keys. A new key is introduced by a bridge release whose binary trusts both the old and new keys and whose manifest both keys sign, so older Strata builds keep updating in place while releases stay dual-signed. Once releases stop carrying the old key's signature, a build that trusts only the old key cannot update in place and must be reinstalled manually. Strata trusts only the keys compiled into it: there is no network-key override and no automatic trust-on-first-use fallback.
If a signing key is compromised, an attacker holding it can sign updates that every build trusting that key accepts. No online revocation claim can repair that trust, and overlapping-key rotation does not protect old builds. Recovery means installing a trusted replacement from an independently verified source.
Rollout and limitations
Releases published before signed updates (v0.21.0 and earlier, and prereleases
before v0.22.0) have no signed manifest. Strata refuses to install them with
"This release has no signed update manifest. Choose a newer release or download
it manually." It never falls back to checksum-only or gh verification. v1.0.0
is the first signed stable release, so Return to stable from a signed prerelease
targets a signed release.
This protocol authenticates release contents and identity, not the initial installation or the freshness of GitHub's release feed. It does not prevent a server from withholding an update. Normal update selection rejects older versions; an explicit user-requested return to stable may intentionally select an older signed version. There is no clock-dependent manifest expiry.
External file providers
File providers add state-dependent context actions and file decorations without loading provider code into Strata. Examples include cloud availability and version-control status. Providers are opt-in trusted programs, not sandboxes; they run with the user's permissions and receive visible native paths. Only install a provider from a source you trust.
Static custom actions continue to use Custom actions. They do not change. A file provider is appropriate when eligibility and state come from an external service and must update while a directory/menu stays open. The browser does not need to know about cloud accounts, pins or service sockets.
Registration and artwork
Install one directory per provider under $XDG_CONFIG_HOME/strata/providers/
(default ~/.config/strata/providers/), then restart Strata. For example:
{
"version": 1,
"id": "example",
"name": "Example Cloud",
"command": ["/usr/bin/python3", "/home/alice/.config/strata/providers/example/provider.py"],
"icon": "logo",
"icons": {"logo": "logo.png", "available": "available.png", "working": "working.png"}
}
Save this as example/provider.json. The manifest must set version to 1 and be
at most 16 KiB. The id is 1–64 ASCII letters, digits or dashes and must match the
directory name. The optional name supplies the human-readable menu group heading; without it,
Strata uses the id. Names must contain non-whitespace plain text, at most 64 UTF-8
bytes, without control characters. The optional icon names one of the declared
icons and is drawn before that heading. If icon names an id that is not in
icons, Strata rejects the registration and the provider does not load. Omitting
icon or setting it to null is accepted. Existing registrations need no changes.
command holds 1 to 16 strings of at most 4,096 bytes each, with no NUL.
Commands are literal argv with an absolute executable; no shell interpolation,
PATH lookup, placeholder expansion or working-directory executable lookup is
performed. The child runs with / as its working directory. Nothing in a browsed
folder registers a provider. Removing the registration and restarting Strata
uninstalls it. Editing a registration takes effect on restart. A relative
XDG_CONFIG_HOME is ignored, and the default location is used.
The providers directory itself, each registration directory, each manifest and
each icon file must be owned by the current user or root, must not be group- or
world-writable, and cannot be a symlink. If the providers directory fails this
check, for example because a dotfile manager made it a symlink, no provider loads.
The executable, command[0], is checked after its symlinks are resolved: the
target must be a regular file owned by the current user or root and must not be
group- or world-writable. A script passed as a later argument is not checked. A
registration that fails any of these checks does not load. Providers can reference
only declared icon ids in replies. Icon ids are 1–64 ASCII letters, digits or
dashes. PNG artwork lives beside the manifest (plain filenames ending in .png,
no subdirectories), at most 64 KiB and 256×256 per image, up to 16 icons.
It is loaded once from trusted configuration, never from selected file content or
URLs. Branded artwork preserves its colors; use artwork legible on both light and
dark backgrounds. Strata's own interface continues to use themed Lucide icons.
Transport
The child reads newline-delimited UTF-8 JSON requests on stdin and writes JSON responses/events on stdout. Flush each line. Stdin/stdout are a private full-duplex socket, not a terminal. Protocol data only belongs on stdout. Provider stderr is discarded, so do not rely on it for user-facing failures or print secrets there.
Every request has version: 1, a unique numeric id, method, paths (absolute
UTF-8 strings), and background (boolean). A background menu has the current
folder as its single path. Non-native and non-UTF-8 paths are not sent. Newlines,
quotes, spaces and Unicode in filenames are JSON data, not delimiters or commands.
query asks for decorations for up to 200 paths:
{"version":1,"id":1,"method":"query","paths":["/home/alice/cloud/report.txt"],"background":false}
{"version":1,"id":1,"decorations":[{"path":"/home/alice/cloud/report.txt","badge":"available","description":"Available offline"}]}
Omit a path or use badge: null to draw no decoration. Replies can only affect
requested paths. A reply holds at most 200 decorations, and a description is at
most 512 bytes. An optional priority is 0 (normal, the default), 1 (warning), or
2 (error); a higher value is invalid. The highest priority wins; equal priorities use the provider id in
lexical order, independent of discovery timing. Accessible descriptions include
all contributing providers, prefixed with their ids. Status badges do not use tooltips. Rows
are rebound to their actual current path; old responses cannot decorate a reused
row. Badges share the thumbnail/icon rendering used by Columns, List and Icons.
The badge is drawn as a square over the bottom-right corner of the file's icon.
Its side is 55% of the icon's shorter side, kept between 10 and 24 pixels.
Non-square artwork is stretched to fit.
menu asks for actions for the entire selection, up to 200 items:
{"version":1,"id":2,"method":"menu","paths":["/home/alice/cloud/report.txt"],"background":false}
{"version":1,"id":2,"actions":[{"id":"keep","label":"Keep offline","icon":"available"}]}
Return an empty actions array for ineligible selections. No placeholder or
disabled global menu item is inserted. Strata always keeps each provider's root
entries together in an inline section with a small, muted, non-interactive
heading. Provider sections appear directly after any custom actions and before
the remaining built-in commands. When several providers answer, their sections
follow the byte order of their registration directory names. This is not an
extra submenu: providers choose flat actions, recursive
submenus, or a mixture within their section:
{"version":1,"id":2,"actions":[{"id":"share","label":"Copy share link","context":"opaque-selection-token"},{"id":"offline","label":"Offline availability","children":[{"id":"keep","label":"Keep offline","icon":"available","context":"opaque-selection-token"}]}]}
Only leaves activate; a branch's nonempty children array is navigation only.
Branches cannot have context. Across the entire tree, allow at most 64 nodes,
four levels (roots are level one), and unique ids of 1–64 ASCII letters, digits
or dashes. Labels are nonempty plain text, at most 128 UTF-8 bytes, without control
characters. Icons are optional declared icon ids. Leaf context is an optional
nonempty opaque string of at most 2,048 UTF-8 bytes. Action and submenu labels
remain as supplied, without repeated provider suffixes. The section heading
identifies their source using the registered name or id, including when different
providers supply identical labels. Empty sections and their headings disappear.
Menus populate asynchronously; retained provider sections and branches reuse
their models on refresh. Removed leaves are disabled before removal, including
when their containing section or branch is withdrawn or the menu closes.
Each menu and activation describes the whole selection, never a silently filtered subset. An adapter may support cross-account selections; otherwise return no actions. For parent/child selections, define whether a recursive operation covers descendants and report counts against the original selection. Deduplication or batching inside the adapter must preserve those semantics. Above 200 items Strata offers no provider actions; it does not truncate a menu or activation selection. Selections must also fit within a request frame: the JSON-escaped path array has a budget of 1 MiB minus 16 KiB reserved for the envelope and context. Larger selections receive no actions; decoration queries split into fitting batches. Oversized host requests are rejected before admission and do not kill an adapter.
activate repeats the exact selection/background, selected leaf action id and
its context, if provided:
{"version":1,"id":3,"method":"activate","paths":["/home/alice/cloud/report.txt"],"background":false,"action":"keep","context":"opaque-selection-token"}
{"version":1,"id":3,"message":"Downloads continue in the service.","outcome":{"status":"accepted","accepted":1,"total":1,"job":"job-17"}}
Revalidate identity and eligibility on activation. A menu is not authorization to act on a replaced file, renamed path or new mount incarnation. Bind context to the exact selection, account/collection/item identities and mount incarnation; reject stale tokens. Enforce identity at the service's operation boundary, not just during a prior path lookup. Strata echoes the token unchanged and replaces it when the same leaf receives new context. A context can also be an adapter's idempotency token; the host neither interprets it nor manufactures replay safety. Adapters without tokens must still guarantee safe identity revalidation.
Every successful activation requires a nonempty plain-text message (at most
16 KiB). Messages and decoration descriptions may contain newlines, carriage
returns and tabs, but no other control characters, including NUL or terminal
escape sequences. An optional outcome object must include status: accepted,
rejected, partial or unknown. A reply with an outcome but no status is
an invalid frame and disconnects the provider.
accepted and total must appear together, with total equal to the original
selection size and 0 <= accepted <= total. Accepted means all submitted;
rejected means none; partial means some but not all. Unknown may report a confirmed
accepted lower bound while other results remain uncertain. Optional job is a
nonempty service reference of at most 128 bytes without control characters.
Strata shows the result in a File availability dialog. The dialog starts with
the provider id, then a status (Accepted, Rejected, Partially accepted or Outcome
unknown) with any counts, such as (1/1), then Job: <job>, then the message.
An unknown outcome shows its counts as a lower bound: at least N/M accepted.
Message-only legacy replies show the provider id and the message; they remain
supported, but do not imply confirmed acceptance or completion. When the
provider's queue is full, the dialog says the provider is busy or unavailable and
the action was not sent. After a disconnect, it says either that the action was
not sent or that it may already have been accepted.
Optional feedback chooses how a successful result is presented: dialog (the
default), notice for a non-blocking notice in the window's progress dock, or
none when the service presents its own interface, such as a share
window. It is honored only with outcome.status accepted; rejected, partial and
unknown outcomes, message-only replies, and disconnects always use the dialog.
Unrecognized values also use the dialog. The message remains required either way.
The notice shows the provider's name, or its id, above the message for about
four seconds, and replaces any notice still visible. The notice wraps the message
and cuts it off with an ellipsis after three lines. Where no notice can be shown,
the File availability dialog opens instead, showing the provider's name, or its
id, followed by the message.
{"version":1,"id":3,"message":"Link copied.","outcome":{"status":"accepted"},"feedback":"notice"}
After every activation reply, Strata treats all of that provider's answers as
invalidated. It re-queries the provider's visible badges and open menus without
waiting for an invalidate event.
Long operations should be submitted as service jobs. There is no automatic retry of actions, including after a lost reply. An unsent action is distinguished from an action whose outcome is unknown; a disconnect after submission must not be represented as proof that nothing happened. Partial acceptance is not a transaction rollback. Check service state before a manual retry.
To mark cached answers dirty, emit an event at any time. An optional paths array
scopes it to 1–200 absolute native UTF-8 roots; omission means all paths, and
an empty array is invalid:
{"version":1,"event":"invalidate","paths":["/home/alice/cloud"],"revision":17}
Use a provider-session monotonic unsigned revision for reliable snapshot
ordering. A query/menu reply's revision identifies the coherent snapshot used for
that selection. It must cover every preceding relevant invalidation; a reply older
than such an event is rejected. Unrelated roots do not reject it. Invalidation
roots overlap selections in either ancestor/descendant direction, at component
boundaries; paths use lexical spelling, so adapters should consistently normalize
their native roots without resolving selected content or symlinks.
Strata preserves wire order across events and replies. A change emitted after a valid snapshot marks it dirty for another refresh, while retaining presentation. This guarantees progress for coherent snapshots under sustained activity, without treating a reply older than a preceding relevant event as current. Once any revision is used, all subsequent invalidations and successful query/menu replies in that process session need revisions; invalidation revisions cannot decrease. Breaking either rule disconnects the provider. A process restart begins a new session and may restart its counter at zero.
Legacy unversioned events are refresh hints. Their query/menu replies must still be coherent snapshots at emission time; Strata accepts them while retaining the need to refresh if a hint crossed the request. Without revisions the host cannot detect an adapter emitting an obsolete snapshot. New adapters should use revisions and scoped invalidations rather than global hints for unrelated account activity.
Invalidate on mount disappearance, disconnect/reconnect or lost event history. An empty method-specific answer withdraws presentation immediately. An event alone does not erase a valid answer: it requests its replacement. Provider disconnects withdraw everything. A five-second refresh interval is a fallback; an answer not replaced expires after fifteen seconds. Identical answers do not rebuild menus or clear badges, and open submenu models survive retained-branch refreshes.
Compatibility
Unknown additive fields in manifests, requests and responses should be ignored;
known fields must retain their types and bounds. A response has exactly one of
id or event. The only event is invalidate. Any other event name, an event
carrying decorations, actions, outcome or error or a nonempty message,
and an id reply carrying paths are invalid frames and disconnect the provider.
A valid reply whose id matches no outstanding request is ignored. Successful queries require decorations, menus require actions,
and activations require message. Legacy adapters may additionally include empty
actions/decorations arrays for another method. Missing required fields,
duplicate tree ids, unknown icons and malformed outcomes are protocol errors.
feedback belongs only to activation replies. A feedback value that is not a
string or null is an invalid frame. So is feedback on a query, menu or
error reply or on an event. Either one disconnects the provider. An
unrecognized string is not an error; it uses the dialog.
Providers must not send nonempty fields belonging to another method.
For an unsupported method or request, reply with the request id, a bounded slug
error such as unsupported-method, and an optional human-readable message;
omit actions, decorations, outcome and feedback. A method error withdraws that
requested presentation without killing the provider. An error reply to activate
opens the File availability dialog with the provider id and the optional
message. Without a message, the dialog says "The provider did not report an
outcome." Version 1 has a fixed baseline and no
handshake: hosts only send the three methods above. Do not require a startup reply
or a capabilities request. A future optional negotiation must preserve that baseline.
Bounds and failure behavior
At most eight registrations are loaded (from at most 64 directory entries), with one child per provider. Strata sends one request at a time on each connection; serial adapters are supported, and events may arrive at any time. It queues up to 16 speculative query/menu requests and eight activations separately. User actions have dispatch priority after the current request; pending refreshes for the same visible path/menu are coalesced by the host. A full queue rejects admission, never kills a healthy process. An action rejected at admission was not sent and is not retried. Replies have 32 reserved queue slots; reading events continues while new dispatch is paused for host backpressure. Events coalesce only between replies, with independent per-root revisions. More than 200 roots or 64 KiB of root strings in one event batch conservatively becomes a global invalidation.
Each response frame, excluding its newline, is limited to 1 MiB; adjacent valid frames do not share that bound. Native paths are at most 16,384 UTF-8 bytes. Requests time out eight seconds after dispatch, not admission; socket writes after 250 ms. Invalid frames, excessive output and timeouts disconnect the provider; its process group is terminated and its state is withdrawn. Strata starts a provider's process when it first sends that provider a request. After a disconnect, it waits two seconds and starts a new process at the next request. Actions in flight are reported as uncertain, unsent queued actions as unsent; neither is replayed. Disconnect updates retire only requests from the failed session; requests admitted afterward keep their outcome tracking across restart.
The GTK thread does not perform provider socket or subprocess I/O. It applies completed bounded batches on its main loop. Each provider cache holds at most 2,048 path answers and 32 menu selections; at most 1,024 live thumbnail slots are tracked. Only mapped slots are queried. Unmapped slots lose their decoration and re-register on mapping; slots refused at capacity retry admission while mapped.
Strata logs bounded static failure categories and validated provider ids for rejected registrations, spawn/transport failures, timeouts and malformed output. Repeated transport diagnostics are rate-limited to once per ten seconds. Host saturation is a separate busy/unsent condition, not an adapter protocol fault. Raw stdout, stderr, command arguments, selected paths, context tokens and messages are never included in these diagnostics.
This API does not authorize downloading file content to calculate presentation. Use cached metadata/service status and never inspect selected documents merely to draw a menu or badge. This is a provider obligation, not an enforced security boundary: a trusted child has the user's permissions. Strata's existing thumbnail/preview behavior is separate. Remote-only locations and non-UTF-8 filenames are unsupported; no lossy conversion is performed.
Preview sandbox
Strata treats files shown while browsing as untrusted. Original-file native parsing and decoding run inside bubblewrap, never in the application. A decoder that crashes, hangs, or is attacked by a crafted file stays inside a short-lived, resource-limited process with no network, no desktop session, and no view of your other files. Strata shows the file's icon or a message instead of the preview.
This page covers what runs in the sandbox, the limits you can run into, and what you see when a preview fails. How the isolation works (namespaces, Landlock and seccomp, the worker processes, and the decoder protocol) is documented for contributors in docs/preview-sandbox.md.
Providers
- GDK Pixbuf/camera RAW, Poppler PDF, ImageMagick, and dcraw fallbacks normalize images to dimension- and size-bounded PNG images. A RAW file that GDK Pixbuf cannot decode falls back to ImageMagick, then to the embedded camera JPEG. Sony ARW files keep their extension inside the sandbox so they decode as RAW.
- An image too large to decode within the sandbox's frame budget (about 134 megapixels) shows its embedded EXIF thumbnail when it has one, and otherwise fails. Typical phone photos, such as a 12-megapixel JPEG, fit the limits; a 200-megapixel photo exceeds the budget. Image helpers limit their memory allocator's arenas, so a JPEG with an embedded ICC color profile also previews on a many-core host, such as one with 64 threads, without the helper hitting its address-space limit.
- SVG and gzip-compressed SVGZ files, detected by content rather than by name,
render with
resvginside the sandbox. An SVG over 8 MiB uncompressed, or oneresvgcannot parse, falls back to GDK Pixbuf or ImageMagick inside the same sandbox. User SVG and SVGZ previews, SVG thumbnails from the worker pool, Markdown SVGs, Mermaid diagrams, and equation output use this path, with image references disabled and system font loading enabled only when the document contains text. Without the worker pool, SVG thumbnails go through GDK Pixbuf or ImageMagick instead. SVGZ files preview but keep their file icon in the browser, because.svgzis not on the thumbnail extension list. ffmpegthumbnailer(or the software FFmpeg fallback) produces bounded media thumbnails. Browser thumbnails and the browser's media-metadata probes (the dimension and duration details in Icons view) share the reusable sandbox workers described below; File Properties inspection does not. Duplicate requests share work, and thumbnail failures are cached for 30 seconds.- Audio and video previews decode in the sandbox and stream to Strata, as described under Incremental media playback.
- Plain text stays in-process, invokes no native format parser, and is capped at 1 MiB.
- Local XLS, XLSX, and ODS previews run inside the resource-limited helper, accepting at most 20 MiB of input. Only validated, bounded cell values cross back into the application; macros and formulas are not executed.
- Local DOCX previews run in the same helper under the same 20 MiB input limit.
- Local Markdown, bounded HTML, RTF, CSV, and TSV previews are parsed in-process by pure-Rust parsers that receive only the bounded source string and cannot initiate filesystem access, network access, JavaScript execution, or subresource loading. Relative Markdown images are separately confined to the document directory. Their decoders, the Mermaid renderer, and the bundled MathJax equation renderer run in the sandbox. User equations are passed as data, not evaluated as JavaScript, and only validated PNG output returns.
- File-list thumbnails are chosen by file extension. They cover PNG, JPEG, WebP, GIF, BMP, TIFF, SVG, HEIC, HEIF, AVIF, and JPEG XL images when a decoder for the format is installed; camera RAW files, from the embedded camera preview first; PDF; MP4, MKV, WebM, MOV, AVI, M4V, MPEG, MPG, and OGV video; cover art in MP3, FLAC, M4A, M4B, MKA, AIFF, AIF, and WMA files, at its aspect ratio, but never in Ogg, Opus, or WAV; embedded 3MF and FreeCAD images; and CBZ, CBR, and EPUB covers.
- An AppImage keeps its type icon. Strata does not show the icon embedded in
the AppImage, whether or not
squashfs-toolsis installed. - A file shows its type icon while its thumbnail loads, and keeps it when rendering fails or the type is unsupported. Folders never get thumbnails, and a file or folder with a custom icon shows that icon instead. Ctrl+F filter results and recursive search results get thumbnails in Columns, List, and Icons, and changing the query leaves no stale thumbnails behind. Renaming a file without changing its extension, size, or modification time keeps its thumbnail without decoding again.
- A fresh image decode in the worker pool also fills the item's Icons caption
with the source dimensions, such as
320×180, without waiting for a metadata probe. A thumbnail served from the in-memory cache gets its dimensions from the separate metadata probe instead.
Every image renderer must return a regular PNG file of at most 32 MiB within the operation's bounds: 800×800 pixels for an image, cover, or document-media preview; 256×256 for a thumbnail; and for a PDF page, the preview pane's width up to 1280 pixels, at most 1800 pixels tall and 2.5 megapixels. Anything else, such as a symlink, an empty file, or oversized output, is rejected. PDF pages render one page at a time across all previews, and queued pages scrolled out of view are cancelled before rendering.
A small image keeps its own size and is enlarged at most 2× to fit the pane. An image or PDF preview never uses the file-list thumbnail as a placeholder; it waits for its own bounded render.
Local 3D model previews
The preview accepts STL, 3MF and FreeCAD (.FCStd) files. STL and single-part
3MF geometry use a fixed-angle software render; FreeCAD uses its saved image,
so FreeCAD need not be installed.
A 3MF package with exactly one usable embedded PNG uses that image, even if other
candidates are corrupt or its geometry spans multiple model parts. Two usable
images are ambiguous: the preview tries geometry, while browser thumbnailing
leaves the normal file icon. Multipart geometry is not rendered: the preview
shows "Multipart model detected. Unable to render preview."
While a model loads, the preview shows "Reading model…", "Rendering N triangles…", then "Finishing preview…"; an embedded image shows "Reading thumbnail…" instead of the triangle count.
Browser thumbnails extract embedded images only, through the browser worker pool and its normal cache. There is no geometry thumbnail for STL. Missing or unusable images leave the file icon, and the failure cache prevents immediate retries.
Heavy previews (models, PDFs, workbooks, DOCX, and comic and EPUB covers) take turns, one at a time across the application, each in its own one-shot sandbox. Geometry renders use the theme's palette, and open model previews reload when the theme changes.
These limits are built into Strata, not Settings options or environment variables:
| Limit | Applies to |
|---|---|
| 128 MiB (134,217,728 bytes) | Input file, including embedded-thumbnail requests |
| 128 MiB, independently of compressed file size | Unpacked 3MF model XML |
| 256 | All ZIP entries in a 3MF package |
| 4096 | All ZIP entries in a FreeCAD package |
| 1024 | Objects in the 3MF model XML |
| 1024 | Build items in the 3MF model XML |
| 16 | Component nesting below a build item (depth zero) |
| 64 KiB | Unpacked _rels/.rels in a 3MF package |
| 2 million | Parsed/emitted triangles |
| 2 million | 3MF vertices |
| 100,000 | Stored component references |
| 100,000 | Expanded objects, including pending expansion work |
| 100 million | Triangle bounding-box pixel visits |
Package entry caps are checked before looking for an embedded thumbnail. A
package exceeding its entry cap is rejected even if it contains a usable PNG:
the preview shows "This model is too complex to draw within the preview
rendering limit. Try a lower-detail version." and the browser keeps the normal
file icon. The _rels/.rels byte limit also applies before thumbnail
selection in 3MF packages. Object, build-item and component limits apply when
geometry is parsed, not when a usable embedded image is selected. Render output
is at most 800×800 pixels.
A model over a limit shows a message instead of a render:
| Limit exceeded | Message |
|---|---|
| Input file over 128 MiB | "This model file exceeds the 128 MiB preview limit. Try a smaller or lower-detail version." |
| Over 2 million triangles | "This model exceeds the 2 million triangle preview limit. Try a lower-detail version." |
| Over 2 million 3MF vertices | "This 3MF model exceeds the 2 million vertex preview limit. Try a lower-detail version." |
| Unpacked 3MF model XML over 128 MiB | "The unpacked 3MF model exceeds the 128 MiB preview limit." |
| Package entries, objects, build items, components, or embedded-image candidates | "This model is too complex to draw within the preview rendering limit. Try a lower-detail version." |
Other failures show their own message: "This FreeCAD file has no usable embedded thumbnail", "STL contains no valid triangles", "3MF contains no printable triangles", "3MF package has no model", "Model has no visible extent", or "External 3MF model references are not supported". Any other parse failure shows "This model file is invalid or damaged."
These input-size limits are not RAM limits. Input, parsed geometry and codec allocations consume additional memory. The sandbox's CPU, wall-time, and 2-GiB address-space limits remain a last-resort boundary.
Embedded images are limited to at most 16 candidates, 4 MiB per candidate, 16 MiB total candidate bytes read and 16 megapixels (16×1024×1024 pixels) total admitted to decoding. Oversized or invalid images are not usable; exhausting a total inspection budget fails the operation rather than assuming uninspected candidates are invalid. Thumbnail output remains at most 256×256, in the image's original colors.
Comic and EPUB covers
CBZ and CBR files show their first image in natural order, and EPUB files their declared cover. A file without one shows an error in the preview and keeps its icon in the file list, as does a damaged cover. Cover thumbnails always run in a one-shot sandbox, outside the worker pool. Covers on remote locations are not offered for preview; copy the file locally first.
Browser worker pool
Columns, List, and Icons share one process-wide pool of sandboxed decoders,
started on the first thumbnail that misses the caches and kept across
navigation, view changes, and windows. Thumbnail workers in
Settings → General, under PERFORMANCE, sets its maximum live workers
(default: available parallelism capped at four, or two when detection fails;
range 1–16). Each click saves the count and applies to every window at once,
without a restart, and the same limit caps the preview pool below. The number
between − and + shows the count; clicking it (Reset thumbnail workers)
restores the default. At 16, the + button
(Increase thumbnail workers) is disabled; at 1, the − button (Decrease
thumbnail workers) is. Typing "thumbnail workers", or a term such as
"concurrency" or "decoder pool", in Search settings finds the control. The saved thumbnail_workers
preference takes precedence over STRATA_THUMBNAIL_WORKERS, which seeds the
default when no count is saved. Values outside 1–16 are clamped to that range,
and values that are not a whole number use the CPU-based default.
Lowering the limit lets active jobs finish and retires excess idle workers. The
pool also runs browser media-metadata probes, not preview playback or
Properties inspection.
Idle workers stop after 60 seconds without a job, and the pool can shrink
to zero while Strata stays open. STRATA_THUMBNAIL_IDLE_SECONDS overrides this at
startup (positive integer seconds, capped at 86,400; zero/invalid values use 60).
Busy decoders are never interrupted by idle expiry. New misses start workers
again, within the same limit. This releases sandbox process memory, not
thumbnail caches, so displayed and cached thumbnails remain available. When a
worker is killed, the next request starts a replacement.
To watch worker reuse, start Strata with
RUST_LOG=strata::sandbox::browser=debug. The log records each worker start
("browser sandbox started"), each completed job with its queue and run times,
and idle retirements, without file paths. Opening several uncached files within
the idle timeout should log completed jobs, not a new start line per file.
Each job still runs in a freshly started decoder with its own CPU, memory, and time limits; only the worker that launches it is reused. No GPU, network, desktop display, or session bus is available to these workers. On systems without Landlock ABI 3 (Linux 6.2 or later, with Landlock enabled), each thumbnail runs in its own one-shot sandbox with the same concurrency budget, and Strata logs "Landlock ABI 3 unavailable; retaining one-shot sandboxes". It never decodes without protection.
Scheduling ranks visible items, in reading order, before a margin of 25% around the viewport, and offscreen requests wait until they are scrolled near. Scrolling re-ranks queued work toward the new viewport. Scrolling an item out of range, or reusing its row for another file, cancels its pending thumbnail work, and a result that arrives late never appears on a reused row. RAW, PDF, video, and embedded-model thumbnails and metadata probes together use at most one worker fewer than the limit (minimum one), so ordinary images keep capacity. A file that changes while it is decoded gets no thumbnail from that run. At most one metadata probe occupies the pool at a time. While both kinds are waiting, a probe gets a turn after four thumbnail admissions; a one-worker configuration must serialize decoding and probing.
Still-image previews and document media (images, Mermaid diagrams, equations) use a second pool, so an interactive Space preview never queues behind a scrolled directory's thumbnail flood. With Landlock ABI 3, a preview within 60 seconds of the previous one reuses its worker. Results are cached by file version and operation, so a 256-pixel thumbnail can never satisfy an 800-pixel preview of the same file.
Remote still-image previews
Still images on GIO/GVfs locations (including phone camera, AFC, and MTP storage) can use the preview pane and Space quick preview. The application streams the selected original to a randomly named mode-0600 temporary file before invoking the same image sandbox as local files. Remote names never choose a local path. The displayed entry and its actions retain the original URI.
Still-image transfers have a 64-MiB byte limit and a 30-second total deadline. Known oversized files are rejected before opening; the stream limit also applies when size metadata is missing or inaccurate. At most four transfers/staged originals can be active per process, including ones waiting for cancellation or decoding. A busy request fails with "Too many remote previews are active; try again shortly" rather than starting another transfer.
Changing selection or closing the preview cancels the transfer. A backend that is slow to acknowledge cancellation retains its slot until its worker exits. Partial files are removed on transfer failure, and staged files are removed when the decoder exits. Normal cleanup does not guarantee removal after a process crash or forced termination. Remote previews do not populate the persistent thumbnail cache or the in-memory rendered-preview cache, and originals are never modified.
MOV and MP4 previews use the same staging, with a 256-MiB byte limit and 60-second deadline, and share the four-input limit with images. Playback starts only after download completes.
Remote PDFs, GIF images (static or animated), audio, video formats other than MOV and MP4, 3D models, comic and EPUB covers, workbooks, and DOCX files are not offered for preview: the preview pane clears, Space opens or closes an empty preview drawer, and the context menu has no Quick preview item. In 10xer mode, i, and l or Right in List and Columns, show "Nothing to preview". Copy them locally first. Supported still-image formats continue to depend on installed sandbox decoder tools; HEIC/HEIF can use ImageMagick with libheif inside the image sandbox.
In the file list, files on a GVfs share that has a local FUSE mirror, such as
smb://, get thumbnails once their metadata loads, rendered from the mirror; the
location and the file's actions keep the remote address. Files on a GVfs
location with no local mirror keep their type icons.
Camera file-list thumbnails
Camera thumbnails use the small preview the camera itself provides, not the original. Missing or failed previews leave the ordinary file icon; Strata does not fall back to downloading full photos for thumbnails.
Retrieval is asynchronous, limited to 1 MiB and 15 seconds. These jobs share the browser's thumbnail workers and queues, and scrolling a row away cancels them. The preview is decoded by the same image-thumbnail sandbox, and only the normalized PNG reaches Strata. Camera thumbnails are cached in memory only, never in the persistent thumbnail cache. AFC and MTP file-list thumbnails are not enabled by this path.
Thumbnails appear during the Photos scan: after each batch the scan pauses 200 ms, then waits up to 2 seconds for visible thumbnails. Those load top to bottom and left to right, and re-rank after scrolling. A viewport left at the top stays there as batches arrive; after you scroll, normal anchoring applies. Background selection updates during loading do not scroll List, Icons, or Columns view to the selected photo. Rows from each camera folder appear only after GVfs finishes listing that folder.
Media metadata
File Properties shows available source-media details: image resolution; audio/video duration and overall bitrate; video codec, frame rate and HDR system; audio codec, sample rate, and channel count; and subtitle tracks and chapter counts. These describe the original file, not the preview's scaled frames or resampled audio. Attached album artwork is not reported as a video track, and still images do not show synthetic video timing. For ordinary images and audio/video, missing individual fields are omitted; an unsuccessful inspection shows MEDIA as "Unavailable" without blocking the other file information.
For a local image/*, audio/*, or video/* file, a MEDIA row reads
"Loading…" until inspection finishes. The rows, in order, are:
| Row | Example or format |
|---|---|
| RESOLUTION | "1600 × 900 pixels"; a video with 90° or 270° rotation shows the displayed orientation |
| DURATION | H:MM:SS |
| BITRATE | Mb/s with two decimals from 1,000,000 bit/s, otherwise whole kb/s |
| VIDEO CODEC | "h264" |
| HDR | "HDR10" or "HLG" |
| FRAME RATE | "24.00 fps" |
| AUDIO CODEC | "aac", "pcm_s16le" |
| SAMPLE RATE | "48.0 kHz" |
| CHANNELS | "1 (Mono)", "2 (Stereo)", or the channel count |
| SUBTITLES | The track count, then the known languages in parentheses |
| CHAPTERS | The chapter count |
A non-media file such as readme.md shows no MEDIA row, and a remote file shows
no media section. The details scroll inside the dialog, so the permission
controls stay reachable below several media rows.
Only regular files with a local source are inspected; remote files are not
downloaded for metadata. The inspector runs ffprobe inside the software-only
sandbox, with a four-second probe timeout and a 256 KiB output limit. Image
information can fall back to GDK Pixbuf inside that same sandbox. Only validated
numeric fields and bounded codec identifiers reach the UI, not arbitrary
embedded tags. Closing Properties cancels its work and prevents stale results
from appearing. Image and audio previews keep their normal size, modified date,
and type information and do not run this inspector. Video previews also keep
Size, Modified, and Type. They run the inspector only for their header badges
and the timeline's chapter ticks and titles (see Video previews),
and show none of the Properties media rows, such as RESOLUTION or BITRATE.
A file whose name ends in a camera RAW extension, such as .DNG, .NEF, .CR3,
or .ARW in any case, shows seven RAW rows in place of the media rows:
DIMENSIONS, CAMERA, LENS, FOCAL LENGTH, SHUTTER SPEED, ISO, and GPS
COORDINATES, in that order, in both the preview panel and Properties. A
readable RAW shows values such as 600 × 400 pixels, 50 mm, 1/250 s, 400,
and -12.500000, -45.250000. All seven fields remain visible; missing or
unreadable values show N/A. Selecting a non-RAW file removes the RAW rows from
the preview panel. Dimensions describe the original image, account for orientation,
and never use an embedded thumbnail's size. GPS is signed decimal latitude,
then longitude; there is no reverse geocoding or network request. Shutter speeds
use 1/N s for integer reciprocals and decimal seconds otherwise (for example,
0.3 s, not 1/3.333 s).
RAW inspection uses LibRaw's raw-identify -v or classic dcraw -i -v when
installed, with a three-second limit per identification attempt. A bundled
EXIF reader supplements capture and GPS tags from supported EXIF containers,
including TIFF-based RAW files, without decoding pixels. It is also the fallback
when those optional utilities are absent. Support depends on the format and
available tools; unavailable tags in other RAW containers remain N/A.
Both parsers run only inside a short-lived, software-only sandbox with the
512 MiB input limit, memory/CPU/wall-time limits, and a 256 KiB output budget.
Only the seven validated properties reach the UI; camera/lens strings are
bounded plain text. RAW files in Trash show the same values as the original,
even when the stored filename has a collision suffix. Remote RAW files are not
downloaded for metadata and show N/A. Selection changes and closing either
surface cancel pending work. RAW preview labels remain in place during
selection changes and metadata loading; only their values reset to N/A and
update when inspection completes. Detailed RAW inspection does not run for
browser thumbnails.
Incremental media playback
FFmpeg decodes one original local file, read-only, inside the sandbox. Strata receives only bounded, validated video frames and audio samples, and plays them itself. No compressed media reaches an unsandboxed parser, and there is no temporary transcoded copy of the file.
Video timing is normalized inside the sandbox to 30 fps. Audio is 48 kHz stereo.
Audio-only files with no video stream, such as a mono .ogg, play their audio.
Raw H.264 and HEVC elementary streams, such as a bare .h264 file, play from the
start and can seek, even without the extension.
Previews play the entire source, without a 30-second playback cap. Seeking restarts the sandbox at the requested position, rounded down to the 30-fps grid. A seek whose decoder dies before its first frame, as happens past the real end of a truncated download whose header overstates the duration, resumes where playback was instead of ending the preview. Short GIFs loop without restarting a process every cycle; longer GIFs play their complete animation before looping.
Files without a reported duration play until decoded EOF. Their timeline remains unknown and seeking is disabled until the actual end is established; pause/idle resume still retains the playback position.
The decode size follows the pane's logical size times display scale, capped at 1280 pixels on either axis. Frames preserve display aspect ratio, including rotation, without enlarging small sources. Resizes settle for 250 ms; the previous frame remains visible. Shrinking the pane never restarts decoding: the larger frames are downsampled on screen and the next seek or restart adopts the smaller size. Growing restarts at the current playback position only when the fitted frame would grow by 8 % or more, so a resize costs at most one restart. A paused resize/seek stays paused. Mute and volume are saved, start every new player, and apply live to every open player; changes to hardware acceleration apply on the next preview.
Decoded output is checked before Strata uses it. Malformed or truncated output is never shown. Before the first frame it fails the preview as a decoder error; after that, playback restarts at the last position up to 3 times, then fails. Strata holds at most eight decoded frames for a player (50 MiB at the largest size) plus about two seconds of audio, so memory does not grow with clip length. There is no whole-clip media cache. Closing or revisiting a file requires a new decode.
Audio previews
Audio files open in a now-playing view with artwork, tags, a live spectrum, and a waveform scrubber. A file without a title tag shows its name without the extension, and a tagged track number reads "Track 3 of 12". Each part is sandboxed or derived from already-validated data:
- Playback ignores attached pictures, so broken or oversized artwork cannot prevent playback. A real video stream overrides the filename's audio type: the file opens in the video view. Pure audio never restarts on resize.
- Artwork comes from one attached picture (tagged front cover first,
otherwise the first picture), scaled to at most 800×800 inside the sandbox.
Without embedded art, the first of
cover,folder,front,album, oralbumart(.jpg,.jpeg,.png,.webp) in the same local folder is decoded by the sandboxed image-preview pool. Without any art, a theme-colored record spins in its place while playing. - Tags are limited to title, artist, album, album artist, and track number/total. Strata removes control and bidirectional-override characters, collapses whitespace, caps each value at 200 characters, and shows them as plain text.
- The spectrum is computed in the application from the audio it already plays, aligned to what you hear, so no extra parser sees the stream.
- The waveform overview starts only after a track has stayed selected for 50 ms. One overview decode runs at a time at low priority. Changing tracks cancels the decode, a 90-second limit bounds it, and finished overviews are cached in memory for 64 tracks. A file with no audio track or no known duration keeps the plain progress line. A decode that fails or reaches the 90-second limit stops and keeps the levels it had received; a failed overview is not cached.
Audio previews always start from the beginning, like a music player, and do not remember where they stopped. Local video previews reopen where they were closed while Strata keeps running, unless they had played less than a second or reached the end. Remote MOV and MP4 previews always start from the beginning. Positions are kept in memory for the last 128 files and are lost when Strata quits.
Uncached tags and artwork also wait 50 ms; cache hits are immediate. Completed lookups are cached for the last 12 tracks, but failed or cancelled lookups are retried on revisiting. Folder artwork is separately cached for 12 directories. Consecutive audio files reuse one view. The current artwork stays in place while details load, and only different artwork crossfades. While the pane is resized, the artwork scales its cached image, then redraws at the new size 120 ms after the size stops changing. Tag and art rows keep their space while loading, so changing tracks does not shift the layout.
A pane at least 1.12 times as wide as tall puts the art beside the controls; at 0.95 or narrower the art returns on top. When height runs short in the stacked layout, the spectrum hides first, then the art. Clicking the art or the spectrum plays or pauses. Spectrum peak caps hold before falling. Hovering the waveform shows the target time in the elapsed label, and clicking or dragging seeks.
Previous/next skip playlists and MIDI. During filtering they follow visible audio results, including subfolders, and untagged captions read "X of Y in results" instead of "X of Y in folder". Previous and next keep playing if the track was playing. Previous is disabled on the first audio file and next on the last; stepping does not wrap. Playback errors remain visible inside the audio view without disabling track navigation. Tracks never advance automatically.
Video previews
Video files open in a now-playing view of their own, laid out like the audio view: the frame is the hero, the header with the file's position among the listing's videos, such as "2 of 5 in folder", or "2 of 5 in results" while search results replace the listing, the volume control, the title and the badges sits directly under it, then the timeline and the same previous/play/next transport, with the whole stack centred in the pane. The frame holds its place from the first paint, sized by the aspect of its stand-in image, described below, or 16:9 without one, until the video reports its own size. Clicking the frame toggles playback; there is no separate play button over the frame. Consecutive video files reuse one view, like audio. Previous/next step to the previous or next file of the same media family, so audio steps to audio and video to video, following visible search results like audio does. Playback errors show their title and detail inside the view; play is disabled, and previous and next stay usable. The timeline is the audio view's waveform slider, with chapter starts added as ticks.
Badges under the title summarise the file from the same bounded ffprobe
inspection that File Properties uses: resolution class by the long edge (SD,
720p, 1080p, 2K, 4K, 8K), HDR10 or HLG, 10-, 12- or 16-bit, rounded frame
rate, video codec, audio codec with channel layout, and a captions badge,
"CC" or "CC ×N", counting embedded subtitle tracks plus subtitle files named after the video
(clip.srt, clip.en.vtt, and the ass, ssa and sub extensions) in the
original's folder. Chapter starts become ticks on the timeline and chapter
titles join the time in the storyboard bubble; nothing renders subtitles over
the frames. The probe starts after the same 50 ms settle as audio details, is
cancelled when the selection moves on, and completed results are cached for the
last 12 files. Until it answers, empty pills hold the row; a failed probe leaves
the row empty. Badges fade in with a short stagger once per file, or appear at
once under reduced motion.
The timeline shows a storyboard bubble while the pointer hovers or drags: the keyframe nearest that time with its timestamp, or an empty cell until one has arrived. A seek covers the stale frame with the nearest cell until the new frame is decoded, so scrubbing never shows a frozen picture. Storyboard cells are decoded in the sandbox only after the first frame is on screen, share the single low-priority background slot with waveform overviews (storyboard first), and are cancelled when the selection moves on. A board has 8 to 48 cells, one per two seconds, 128 pixels on the long edge. Cells arrive middle first, then the quarters, then the eighths, and so on. Clips under four seconds, animations, attached pictures, raw elementary streams and unknown durations have no storyboard. A 90-second limit bounds the decode, and finished or partial boards are cached in memory for the last 8 clips (about 14 MB for 16:9 video, up to about 25 MB for square video). A partial board keeps its cells, and the next visit to the clip decodes the board again.
Opening a previewed video externally, with Enter, the header's Open in default
application button or activation in the listing, pauses the preview and hands
its position to the default player. A file opened while its preview is still
loading, as the second click of a double-click does, stays paused once that
preview lands instead of autoplaying beside the player; moving to another file
or pressing play lifts the hold. mpv, VLC, Celluloid and MPlayer start at the
preview's position, including through env and Flatpak wrappers. Unknown
players, failed timed launches and positions within a second of either end open
the file plainly.
Autoplay media previews (Settings → General, under BROWSING) is off by default: a selected media file shows paused with a play control. A playing preview hidden by a narrow window resumes when shown again, whatever the setting.
With Autoplay media previews on, playback starts silent and rises to the saved volume, which it never changes: over 1 s from the first frame for video and over 0.5 s from the first sample for audio. Files shorter than 10 s play at full volume from the start; unknown durations ease in. A muted saved state skips the ramp, and any play, pause, seek, volume or mute input, or moving to another file, ends it immediately.
Ambient light bleeds the frame's border colours into a 24-pixel band around the picture, sampled from decoded frames at most ten times a second. While the poster stands in, the band takes its colours from the cached thumbnail and eases to the live frames. Nothing updates while playback is paused. The light follows Element glow in Settings → Appearance, stays off under reduced motion, and never runs on the Cairo software renderer.
The frame area never shows a spinner. Until the first decoded frame it shows the listing's cached thumbnail dimmed as a poster when that thumbnail is already in memory, otherwise a plain surface at the probed aspect. A clip that resumes where it stopped shows the cell of its cached storyboard nearest that point instead. The first frame fades the stand-in out over 150 ms, or replaces it at once under reduced motion. Every media stream waits 50 ms before starting its sandbox session, so a selection that moves on within that window spawns no decoder.
Scheduling and deadlines
At most four media sessions per application process may own decoders, across browser windows and file choosers sharing that process. A fifth request shows "Media previews are busy (four active players). Pause or close another preview and retry." instead of interrupting another player. A player keeps its slot while it plays out buffered frames, so a fifth player cannot take it between GIF loops. Separate application and file-chooser processes have separate limits, not a machine-global scheduler.
| State | Bound / behavior |
|---|---|
| Startup or seek | 22 seconds from request to first frame; includes a 4-second probe, hardware attempts of at most 4 seconds each / 8 seconds combined, and up to 8 seconds for software. Isolated seeks restart at once; bursts within 200 ms coalesce to the settled position. |
| Active decoding | 8 seconds for a complete next frame. A stall mid-playback (frozen audio clock, decoder failure, audio-output error) restarts at the last position up to 3 times, then fails with the last error. |
| Audio clock | Until audio output first advances after a start, seek or resume, the playhead and video hold their position, so a start-up delay, such as Bluetooth audio over PipeWire, never snaps the playhead back. After the clock has run, a stalled clock lets video run ahead by at most 2 seconds, and playback restarts after 3 seconds without progress. |
| Paused | Keep position, frame and buffers for 30 seconds, then stop the decoder and release audio output. The displayed frame and position remain. Resume or a paused seek starts a new decode. |
| Close / selection change | Cancel promptly and stop the decoder and its sandbox. |
| End / malformed output / failure | Release the decoder; malformed or truncated output, unavailable decoding and unsuccessful exit fail closed. No unsandboxed fallback. |
The limits do not promise instant startup, zero-latency seeking, or a total RAM plateau for every toolkit/driver.
Isolation and hardware policy
Strata starts bubblewrap only from admin-managed system locations
(/run/wrappers/bin, /usr/bin, /usr/sbin, /bin, /sbin, and the NixOS and
Guix system profiles), never from your PATH. A copy whose real location is
outside the system directories, /nix/store, or /gnu/store is refused. When
bubblewrap is missing or cannot start, a native-format preview shows Preview
unavailable with the reason, and the file is never decoded outside the
sandbox.
Packagers of non-FHS distributions can point the sandbox at their runtime tree with these variables when compiling Strata. They are embedded in the executable; setting them when launching Strata has no effect.
| Build-time variable | Default | Purpose |
|---|---|---|
STRATA_SANDBOX_PATH | /usr/bin | Colon-separated helper binary directories inside the sandbox |
STRATA_SANDBOX_ROOT | /usr | System runtime tree, bound read-only at the same path |
STRATA_SANDBOX_PRLIMIT | /usr/bin/prlimit | Resource-limit launcher path for one-shot helpers and RAR extraction |
STRATA_SANDBOX_GDK_PIXBUF_MODULE_FILE | Unset | GDK Pixbuf loaders.cache path passed to helpers |
For example, a Nix package can compile with:
STRATA_SANDBOX_PATH='/nix/store/<ffmpeg>/bin:/nix/store/<imagemagick>/bin:/nix/store/<util-linux>/bin:/nix/store/<coreutils>/bin' \
STRATA_SANDBOX_ROOT='/nix/store' \
STRATA_SANDBOX_PRLIMIT='/nix/store/<util-linux>/bin/prlimit' \
STRATA_SANDBOX_GDK_PIXBUF_MODULE_FILE='/nix/store/<pixbuf-loaders>/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache' \
cargo build --release --locked
Replace the store paths with your package's dependency paths, and include every
helper binary directory. Values are used literally: leave a variable unset to
keep its default, never set it to an empty value. The resource-limit launcher,
the helper binaries, the loaders cache, its modules, and their runtime libraries
must all be reachable inside the sandbox mounts. STRATA_SANDBOX_PATH,
STRATA_SANDBOX_ROOT and STRATA_SANDBOX_GDK_PIXBUF_MODULE_FILE apply to every
sandbox: one-shot previews, the browser worker pools, media playback, and RAR
extraction. STRATA_SANDBOX_PRLIMIT applies only to one-shot previews and RAR
extraction. Media playback, waveform and storyboard helpers run prlimit, and
nice for background decodes, from STRATA_SANDBOX_PATH, so that path must
include the util-linux and coreutils binary directories.
The root replaces /usr rather than adding a mount. Use only admin-managed
runtime trees: binding / or a user tree exposes private files to untrusted
decoders.
Each sandboxed helper sees:
- read-only system libraries and tools, the Strata executable, and exactly one read-only input file;
- a private output directory for image providers and a size-limited (512 MiB)
private
/tmp; - an empty environment, a nonexistent home, and no network, desktop, session-bus, or audio-server sockets. Only the application handles display and audio output.
Image/PDF parsing has a 512-MiB input cap, 2-GiB address-space cap, 512-MiB file cap, 32-MiB output cap, 12-second wall limit and 10-second CPU limit. A larger input fails with "Preview input exceeds the supported size limit" before any renderer starts. Changing selection or closing the preview kills the helper and everything it started. Media has no input-file size cap, playback-duration cap, or cumulative CPU limit; frame sizes, buffer limits, and the deadlines above bound active work. Each software FFmpeg process has a 2-GiB address-space limit; all decoding processes disable core dumps and cap files and individual media allocations at 512 MiB and source frames at 50 million pixels. Hardware decoders are exempt from the address-space limit because drivers reserve large virtual ranges.
Hardware decoding is controlled by Hardware-accelerated video previews and
Decoding backend (Automatic, VA-API, or Vulkan) in
Settings → General, under PERFORMANCE. Automatic tries VA-API, then
Vulkan, then software. Explicit VA-API/Vulkan falls directly back to software
when its hardware attempts fail before output begins. A decoder never switches
backends partway through a stream. If decoding fails after playback starts,
Strata restarts at the last position, up to 3 times, and each restart tries the
hardware backends again before software. Then the preview fails with the last
error.
VA-API receives only GPU render nodes (/dev/dri/renderD*); Vulkan/Automatic
may also receive NVIDIA device nodes. Accelerated helpers receive read-only
/sys for discovery. With hardware acceleration off, and always for audio
previews, waveforms, storyboards, metadata, image, PDF, and thumbnail helpers,
the sandbox receives no GPU devices or /sys mount. With it on, a video
preview's sandbox keeps that access even when it decodes in software, such as a
GIF, a file whose only picture is cover art, or a fallback after the hardware
attempts fail. Changing these settings applies to the next preview
without interrupting the current one.
With no saved choice, systems with an AMD Polaris 10, 11, or 12 GPU (PCI IDs
0x67c0–0x67df, 0x67e0–0x67ff, or 0x6980–0x699f) decode in software.
You can still opt in. GPU access expands the helper's attack surface into
driver code.