Helper functions and the revisions, revset, and context tables are available both as top-level globals and under the jjui namespace — flash(...) and jjui.flash(...) are the same, and revisions.edit() and jjui.revisions.edit() are the same.
Other built-in action scopes (ui, git, diff, oplog, bookmarks, bookmark_pane, annotation, undo, redo, choose, input, command_history, file_search) are only available under the jjui namespace — e.g. jjui.git.push(), not git.push().
Built-in action wrappers are additionally available under jjui.builtin.*, which forces built-in resolution and ignores any user-defined overrides for those action names.
Read-only access to the currently highlighted or selected item.
Function
Returns
Notes
context.change_id()
string
Available for revisions and files
context.commit_id()
string
Available for revisions, files, and commits
context.file()
string
Only when a file is selected in the details view
context.operation_id()
string
Only in the oplog
context.checked_files()
string[]
Files checked in the details view
context.checked_change_ids()
string[]
Checked revisions or files
context.checked_commit_ids()
string[]
Checked revisions, files, or commits
The selection getters read live UI state when called. After a yielding action or
refresh, they reflect the current selection rather than a cached snapshot. This
lets a script refresh the revision list and then act on the selection that is
visible when the refresh completes:
revisions.refresh()
localcommits=context.checked_commit_ids()
if#commits>0then
flash("Selected " ..#commits.." commits")
end
The inline describe editor exposes its current draft through
revisions.inline_describe.content(). It returns the text while the editor is
open and nil otherwise:
Runs synchronously; returns output string and error
jj_async(...args)
—
Queues a command without waiting; its output or error is shown as a flash message when it completes
jj_interactive(...args)
—
Opens an interactive terminal for the command
Args can be passed as individual strings or as a single table of strings.
jj_async does not return command output to Lua or wait for the command before Lua continues. Use jj when later Lua code needs the command’s output or must run only after it has completed.
error = true styles as error; sticky = true keeps it visible
choose(option1, option2, ...)
string or nil
Show a picker; returns the selected value or nil if cancelled
choose({ options, title?, ordered? })
string or nil
Table form; press / in any choice dialog to open the filter: prompt
input({ title?, prompt?, value? })
string or nil
Show a text input dialog; value sets its initial text; returns the entered text or nil
set_theme(name)
—
Switch the active theme at runtime
copy_to_clipboard(text)
(true, nil) or (nil, err)
Copy to system clipboard
split_lines(text, keep_empty?)
string[]
Split on newlines; strips \r; skips empty lines by default
exec_shell(command)
—
Run a shell command line; yields until done
change_workspace(path)
(true, nil) or (nil, err)
Switch the workspace path used by subsequent jj commands
set_theme(name) changes the currently active theme immediately. This is exposed to Lua for custom workflows and plugins, but it is not wired to the UI by default, so you need to call it from your own action, binding, or startup logic.
change_workspace(path) is also available as jjui.change_workspace(path). It changes the workspace directory for command execution without reloading repo-specific jjui configuration.
Every built-in action is exposed as a Lua function via jjui.<scope>.<action>(). These dispatch the action into the UI and yield until it is handled, so they compose naturally with other async steps.
In every scope that has a cancel() action, close() is available as an alias — e.g. jjui.git.close() is the same as jjui.git.cancel().
Actions that take a single required string arg accept it positionally: