Skip to content

User commands

User commands turn shell commands into named Newt actions. They can use the focused file, the selection, and both pane paths, and run in a terminal or as a background operation.

Manage them from the Commands tab in Settings, which also shows a compact template reference while you edit. Press F9 to search and run the commands available for the current item or selection.

Commands are stored as [[command]] entries in settings.toml:

[[command]]
title = "Archive Selection"
run = "tar czf {{ file.stem }}.tar.gz -- {{ files | map(attribute='name') }}"
key = "alt+z"
terminal = true
keep_terminal_open = true
applies_to = "selection"

Only title and run are required:

KeyMeaning
keyShortcut while a file pane has focus. It takes precedence over a [[bind]] for the same key.
applies_tofile, directory, or selection. Limits when the palettes offer the command; omit it to allow any focused item. The command’s own key runs it regardless.
terminaltrue runs the command in a new terminal tab in the active pane’s directory. false (the default) runs it as an operation in the Operations panel.
keep_terminal_openTerminal mode only: keep the tab open after the command exits, even if behavior.keep_terminal_open is off.
silentOperation mode only: show no progress window or panel row. A failed silent command is still shown.

The run value is a Minijinja template. Newt renders it and runs the result in the shell of the machine the session is on: sh -c on macOS and Linux and cmd.exe on Windows, or the remote host’s shell in a remote session. These values describe the current context:

ValueMeaning
fileThe first entry of files: the first selected entry in listing order, or the focused one when nothing is selected. Undefined on ...
file.nameFilename including its extension.
file.pathFull path, as Copy Path gives it (for example C:\Users\… on Windows).
file.sourceOriginal path for a virtual entry such as a search result, when applicable.
file.stem / file.extFilename without its extension / extension without the dot.
file.is_dirWhether the focused item is a directory.
file.size / file.modifiedSize in bytes / Unix modification timestamp.
filesSelected files, or a one-item list containing file when nothing is selected.
dir / other_dirCurrent path of the active / other pane.
hostnameHostname of the computer running Newt.
env.NAMEAn environment variable of the Newt application, for example env.HOME.

file.source, file.size, and file.modified are none when they have no value. In a remote session the command runs on the target, but hostname and env still describe this computer.

Every interpolated value is quoted automatically for the shell the command runs in, so a filename with spaces or shell metacharacters stays a single argument, and a list such as {{ files | map(attribute='name') }} expands to one quoted argument per item. Put -- before file arguments where the program supports it so a name starting with - is not read as an option.

  • Use | raw (or | safe) to insert a value unquoted when it is meant as shell syntax, such as {{ prompt('Flags') | raw }}.
  • Use | shell_quote when building quoted items before joining them yourself (map('shell_quote') | join(' ')); a plain join(', ') joins unquoted strings into a single value, such as for a confirm() message.
  • The path filters basename, dirname, stem, ext, regex_replace, and join_path follow the path conventions of the computer running Newt. Standard Jinja filters such as map, join, upper, and lower are also available.

prompt() and confirm() collect input before the command runs:

[[command]]
title = "Create checksum"
run = "{% if confirm('Create a SHA-256 file?') %}sha256sum -- {{ file.name }} > {{ prompt('Output file', file.name ~ '.sha256') }}{% endif %}"
terminal = true
applies_to = "file"

Newt shows one dialog with all the template’s fields and confirmations, the latter as checkboxes ticked by default; a lone confirm() shows a plain Yes/No dialog. Cancelling or declining any confirmation stops the command, so confirm() is always true when the command runs. Use it in a {% if %} block as above, not in {{ }}, which would insert the word true into the command.