#15970·gitbutler

JSON `--status-after` omits per-commit file lists (works in human mode, not JSON)

Author: dprovderCreated Sep 16, 2026Updated Sep 16, 2026
LabelsbugCLI

Summary

--status-after --json never includes per-commit file lists ("changes" is always null), even though the equivalent human-readable --status-after output does include them. This looks like an asymmetry between the two branches of run_status_after() rather than intended behavior.

Repro

bash
but branch new feat-a
echo one > a.txt
FID=$(but diff --json | jq -r '.changes[0].id')
but commit "$FID" -m first -b feat-a --status-after --json | jq '.status.stacks[0].branches[0].commits[0].changes'
# -> null

but status -f --json | jq '.stacks[0].branches[0].commits[0].changes'
# -> [{"cliId": "...", "filePath": "a.txt", "changeType": "modified"}]

Same workspace, same commit, immediately after — -f-style file detail exists and is queryable, just not through --status-after's JSON path.

Where it comes from

In crates/but/src/lib.rs, run_status_after():

rust
if out.is_json() {
    let status_result = command::legacy::status::worktree(
        ctx, out,
        StatusFlags::all_false(),   // show_files: FilesStatusFlag::None
        StatusRenderMode::Oneshot,
    );
    // combined = {"result": mutation_json, "status": status_json}
} else {
    command::legacy::status::worktree(
        ctx, out,
        StatusFlags {
            show_files: FilesStatusFlag::All,   // human path asks for files
            verbose: true,
            hint: true,
            ..StatusFlags::all_false()
        },
        StatusRenderMode::Oneshot,
    )
}

The human-mode branch explicitly requests FilesStatusFlag::All; the JSON-mode branch calls StatusFlags::all_false(), which sets show_files: FilesStatusFlag::None. That's the entire reason JSON output loses per-commit file detail — there's no flag on commit/amend/move/squash/uncommit etc. to opt back in.

Why it matters

--status-after is documented as folding a mutation and its resulting workspace status into a single call, avoiding a separate but status -f --json round trip. For any tool that renders per-commit file lists (e.g. a TUI showing which files are in a commit), the JSON path currently can't be used for that purpose at all — every mutation would need the extra but status -f --json call anyway, defeating the point of --status-after.

Expected

JSON-mode --status-after includes file details the same way the human-mode path does — either always (matching human mode), or behind a flag consistent with but status -f.

Environment

  • but 0.22.3 (also present as far back as 0.22.1, where --status-after was introduced)
  • macOS