In short: it picks exactly one file the same way config set does, creates it if it does not exist,
and runs ui.editor on the file itself, not a copy. Afterwards it re-parses the file as TOML. If that
fails, it asks whether to keep editing; answering no writes back the contents it loaded before the editor ran.
It never loads the repo and never snapshots.
The command is cmd_config_edit. Its help text: "Start an
editor on a jj config file. Creates the file if it doesn't already exist regardless of what the editor does."
(source). It is the Edit variant of ConfigCommand,
with the visible alias jj config e (source, dispatch).
1. Command-line surface
| Argument | Meaning |
|---|---|
--user | The first user config file (test; source). |
--repo | The repo's config file, kept outside the repo under the user's config directory (source, test). |
--workspace | The current workspace's config file (source). |
--file PATH | A file at a location jj recognizes as config; created with missing parents if absent (source). |
The command has no other arguments: ConfigEditArgs is just the shared target group, of which exactly
one is required (source, group).
The global flags are on the CLI page.
2. Configuration
| Setting | Effect |
|---|---|
ui.editor | The command to run (source). It is read before anything else, so a bad value fails the command before any file is created (source). |
| Built-in default | nano on Unix (source) and Notepad on Windows (source). |
$VISUAL, then $EDITOR | Set ui.editor in the base environment layer, which user, repo and workspace config override (source). |
$JJ_EDITOR | Sets ui.editor in the override layer, above every config file (source). |
The editor is run with the file's path as its last argument, unless the configured command already contains
a $path placeholder; a $line placeholder is also available
(source).
3. End-to-end flow
4. Core architecture touchpoints
| Piece | Role here |
|---|---|
ConfigTargetArgs::edit_config_file | Shared with config set and config unset: turns the target flag into one ConfigFile, or fails with "No user/repo/workspace config path found to edit". |
TextEditor | The same editor wrapper other commands use, but here it opens the config file directly instead of a temporary copy. A non-zero exit from the editor is an error. |
ConfigFile::load_or_empty | Gives a missing file an empty document with the #:schema header, which is what the early save writes. |
Ui::prompt_yes_no | Asks whether to keep editing, defaulting to yes. |
5. What it reads, and snapshotting
It reads the chosen config file, through the config already loaded at startup or from disk, and the edited file again after each editor run (source). It never loads the repo or the working copy, so there is no snapshot. It writes the file when it did not exist, and again only on a restore (source, restore); otherwise the only writer is the editor.
6. Algorithm and invariants
Creating the file first
If the chosen path does not exist, the loaded empty document is saved before the editor starts, so the file
exists even if the editor is closed without saving. For --user and --repo, its
directory is created too (test,
test). The path is printed to stderr as Editing file: PATH
(source).
The edit loop
After the editor exits successfully, the file is parsed with
ConfigLayer::load_from_file, tagged with the file's source.
Only TOML syntax is checked here, not whether the values suit jj's schema. On failure it prints "An error has been
found inside the config:" and the error chain, then asks "Do you want to keep editing the file? If not, previous
config will be restored." (source). Yes reopens the editor on the same,
still-invalid file. No saves the ConfigFile that was loaded before the first editor run, putting
back what was there (source).
Without a terminal
When the session cannot prompt, prompt_choice_with picks the default without waiting
(source). The default here is yes, so with invalid contents the editor is
simply run again.
7. Errors and edge cases
| Situation | Result |
|---|---|
| No target flag | A clap usage error, exit 2 (test). |
--repo outside a repo | Error: No repo config path found to edit, exit 1 (test). |
| No user config file yet | The file and its directory are created, then opened (test). |
| Editor cannot start or exits non-zero | An error; the file is not re-checked or restored (source, source). |
| Invalid TOML, then "Y" | The editor reopens; a later valid version is kept (test). |
| Invalid TOML, then "n" | The previous contents are written back (test). |
8. Example output
From upstream's test, where the editor first writes invalid config here into the repo config
(source):
$ jj config edit --repo
Editing file: $TEST_ENV/home/.config/jj/repos/8e4fac809cbb3b162c95/config.toml
Warning: An error has been found inside the config:
Caused by:
1: Configuration cannot be parsed as TOML document
2: TOML parse error at line 1, column 9
|
1 | invalid config here
| ^
key with no value, expected `=`
Do you want to keep editing the file? If not, previous config will be restored. (Yn): Y
The second editor run writes test="success", and afterwards:
$ jj config get test
success