05. Commando — Multi-panel mode

Commando is the default mode. It opens when you launch dedcom without flags (or explicitly with dedcom --commando). The alternative is the step-by-step wizard dedcom --classic (§06).

This is a multi-panel navigator in the spirit of classic two-panel file managers: 2–4 independent panels, each showing something of its own (the files of a directory, duplicate groups, the files of a selected group, and so on). The main difference from those is that panels can be "watch" modes and switch automatically as the cursor moves in a neighbouring panel.

Screen anatomy

┌─ DedupCommando v0.9.0-beta.1 ────────────────────────  RAM 47.2M · CPU  3% ┐ ← header
│ Multi-panel mode     ZFS: datasets 8     scan #5 · 2 h ago                  │ ← info line
├──────────────────────────┬──────────────────────────┬──────────────────────┤
│ /tank · files · name     │ /tank · groups           │ Group files #5       │
│ ▸ media/                 │ #1 ●●●●  72.4M × 23      │   /tank/IMG_3120.HEIC│ ← 2–4 panels
│   backup/                │ #2 ●●●●  45.0M × 18      │ K /tank/IMG_canon.HEIC│
│   old/                   │ ▸ #5 ●●●  25.7M × 10     │ H /tank/dup.HEIC     │
│   iso/                   │ #6 ●●●   18.9M × 8       │ H /tank/copy.HEIC    │
│   .dedcom-quarantine/    │ ...                       │ ...                  │
├──────────────────────────┴──────────────────────────┴──────────────────────┤
│ Panel 1 · /tank · files: 5 · sort: name · v view · s sort · m layout       │ ← status
│ 1Help 2Scan 3File 4Hash 5Hard 6Ref 7Keep 8Del 9Menu 10Exit 11Exec 12Sessions│ ← F-keys
└─────────────────────────────────────────────────────────────────────────────┘
  • Header — the brand title, the version, and the process RAM/CPU badge.
  • Info line — the mode, how many ZFS datasets the host reported (and how many startup warnings, if any), and the active scan: its number and age, (loading…) while its results load, or no scan for <folder> · F12 — select.
  • Panels — from 2 to 4; the ones that fit the window width are visible. If the window is narrow, the extra panels are "hidden", with a count in the status line.
  • Status line — a short hint for the active panel plus the relevant single-character keys.
  • F-key footer — the numbering (1 = F1, …, 12 = F12). The background color changes when the second layer is armed (see below).

Basic panel control

KeyAction
TabFocus the next panel (cyclic)
Shift+TabFocus the previous panel
← / →Focus the previous / next panel
↑ / ↓ or k / jCursor up / down
PgUp / PgDnCursor by ±15 rows
Home / EndCursor to the start / end of the list
EnterEnter a directory / open an entry (depends on the view)
BackspaceGo up to the parent directory

Each panel's cursor is independent. Tab does not "reset" the cursors — they remember their positions.

Add and remove a panel

KeyAction
Shift+F3 or ` F3Add a panel (≤ 4)
Shift+F4 or ` F4Remove a panel (≥ 2)

If the window is too narrow for all panels, the hidden ones are shown as a "hidden panels: N — widen the window" note in the status line.

Change the panel root

KeyAction
Shift+F5 or ` F5Change the active panel's root (to the next ZFS dataset, cyclic)

Useful for hopping between datasets quickly without cd by hand.

Synchronize and compare panels

KeyAction
Shift+F1 or ` F1All panels → the active panel's directory
Shift+F2 or ` F2Compare the files and folders in the open panels
, (comma)Side-by-side comparison (on/off, see below)

Panel views (cycled with the v key)

Each panel chooses for itself what it shows. The views cycle with the v / V key:

Files → DirsOnly → GroupList → GroupFiles → DuplicatesOfCursor → DirGroupList → DirGroupFiles → (Files)
ViewHeader labelWhat it showsData source
FilesfilesThe ordinary navigator: files and subdirectories of the current dirReal FS
DirsOnlydirectoriesSubdirectories only (no files)Real FS
GroupListgroupsThe duplicate groups of the whole loaded scan, sorted "by benefit"Scan DB
GroupFilesgroup filesThe files of the group selected in the neighbouring GroupList (watch)Scan DB
DuplicatesOfCursorduplicatesDuplicates of the file under the cursor of the neighbouring Files panel (watch)Scan DB
DirGroupListdirectory groupsThe list of groups of twin directories (see below)Scan DB
DirGroupFilesgroup directoriesThe directories of the group selected in the neighbouring DirGroupList (watch)Scan DB

When to use which view:

  • Files + DuplicatesOfCursor (two neighbouring panels): "I walk through my directory and immediately see whether a file has duplicates anywhere else." One of the main working scenarios.
  • GroupList + GroupFiles (two neighbouring): "I scroll groups by descending benefit and work through the large ones."
  • Files + Files (two neighbouring): just a file browser for comparing two places.
  • DirGroupList + DirGroupFiles: "I found folders with identical content and look at their full paths."

File and directory views: Files / DirsOnly

The ordinary navigator. Enter enters a subdirectory; Backspace goes up.

The panel header is the path, the view label (files / directories), and the sort key.

┌─ /tank · files · name ───────────────────────────────────────────────┐
│ ..                                                                    │
│ media/                                                                │
│ backup/                                                               │
│ old-photos/                                                           │
│ ▸ vm-disks/                                                           │
│ readme.txt                                                            │
│ .dedcom-quarantine/                                                   │
└──────────────────────────────────────────────────────────────────────┘

File-duplicate views: GroupList / GroupFiles

After a scan, a panel can be switched to GroupList — showing all the duplicate groups of the loaded scan:

┌ 1 · groups (by savings) ─────────────────────────────────────────────┐
│▶ #0    2 files · 2 objects · 4.0 GiB                                 │
│    guaranteed after quarantine purge: 4.0 GiB                        │
│  #1    2 files · 2 objects · 700.0 MiB                               │
│    guaranteed after quarantine purge: 700.0 MiB                      │
│  #2    3 files · 3 objects · 24.0 MiB                                │
│    guaranteed after quarantine purge: 48.0 MiB                       │
└──────────────────────────────────────────────────────────────────────┘
  • The first line of a group: its rank (from #0), the number of files, the number of separate copies of the data (objects; files already hardlinked to one another count once) and the size of one file.
  • The second line: the space guaranteed to come back once the copies are dealt with and the quarantine is purged. Groups are ordered by it, largest first.

The neighbouring panel on the right, switched to GroupFiles, automatically shows the files of the selected group — name first, then directory — with the marks saved for them:

┌ 2 · group files ─────────────────────────────────────────────────────┐
│guaranteed after quarantine purge: 48.0 MiB · links seen 3/unrecorded │
│▶ h IMG_3120.HEIC  ·  /tank/backup/photo  -> HARDLINK                 │
│  ★ IMG_3120.HEIC  ·  /tank/media/photo/2021-11  (keeper)             │
│  h IMG_3120.HEIC  ·  /tank/old-copy  -> HARDLINK                     │
└──────────────────────────────────────────────────────────────────────┘

The first column shows a file's saved mark: ★ keeper, h hardlink, c reflink, x delete, = the same file on disk as the keeper. The marks themselves are set in a Files panel (see "File marks" below); in GroupFiles the marking keys are refused, and o opens the file's directory next to it (see below).

On very large groups, GroupFiles shows the first 200 files (a visual cap against freezes). This does not affect the bulk F11 actions. See §13.

The "duplicates of the cursor" view: DuplicatesOfCursor

The neighbouring panel on the right, switched to DuplicatesOfCursor, automatically shows the duplicates of the file under the cursor of the left Files panel:

┌─ /tank/photos · files ──┐  ┌─ Duplicates /tank/photos/IMG_3120.HEIC ────┐
│ ..                       │  │ /tank/backup/IMG_3120.HEIC                  │
│ IMG_3119.HEIC           │  │ /tank/old-copy/IMG_3120.HEIC                │
│ ▸ IMG_3120.HEIC         │→ │ /tank/media/dup.HEIC                        │
│ IMG_3121.HEIC           │  │ (4 copies in total, including the current)  │
└─────────────────────────┘  └──────────────────────────────────────────────┘

The cursor moved in the left panel → the right one updated instantly (in the background, no freeze).

Directory-twin views: DirGroupList / DirGroupFiles

While scanning, DedupCommando builds directory signatures — two directories with identical signatures have identical content (recursively). Groups of such "twin directories" are available through the DirGroupList view:

┌─ Directory-twin groups (47 groups) ─────────────────────────────────┐
│ #1   45.2 GiB × 3 directories  /tank/backup/2023-archive/           │
│ #2   12.7 GiB × 2 directories  /tank/media/photo/canon-raw/         │
│ ▸ #3  8.9 GiB × 4 directories  /tank/old/projects/                  │
│ ...                                                                  │
└──────────────────────────────────────────────────────────────────────┘

The neighbouring DirGroupFiles shows the full paths of all the directories in the selected group:

┌─ Group directories #3 (4) ──────────────────────────────────────────┐
│ /tank/old/projects/                                                  │
│ /tank/archive/2022-projects/                                         │
│ /tank/backup/projects-bak/                                           │
│ /tank/restore-test/projects/                                         │
└──────────────────────────────────────────────────────────────────────┘

Which algorithm builds the signatures (default vs --merkle-dirs) — see §07 Scanning.

The o key — a file's directory into the adjacent panel

In the GroupFiles and DuplicatesOfCursor views, the o / O key opens the directory of the file under the cursor in the adjacent panel on the right, in Files view, and the cursor there lands on that file immediately. This is the way from a group to its files for marking (§04 Step 8).

If there is no right panel, o adds one, and the new panel takes the focus; a narrow terminal or the panel limit puts the error text into the status line instead. When the panel on the right already exists, the focus stays where it was. In other views, o does nothing but set the status message "The «o» key works in the «group files» and «duplicates» modes".

Watch modes: how panels "follow" one another

The GroupFiles, DuplicatesOfCursor, and DirGroupFiles views are "watch" modes. Each such panel looks at the cursor of the neighbouring panel on its left and updates automatically.

Watch viewSource in the neighbour on the left
GroupFilesGroupList — the selected group
DuplicatesOfCursorFiles / DirsOnly — the file under the cursor
DirGroupFilesDirGroupList — the selected group

If the neighbour has no suitable source (for example, it is in Files mode on a directory without duplicates), the watch panel shows "no data".

Watch updates in the background — navigating in the source does not "hang" on a DB query from the right.

Sorting entries (s / S)

The sort keys cycle with the s / S key in the active panel:

name → size → type → date → (name)

The panel header shows the current key.

File marks

A mark lives on the absolute path — moving to another directory does not lose it.

MarkGlyphKeyMeaning
KeeperKF7The group's keeper file (one per group)
HardlinkHF5Replace with a hardlink to the keeper
ReflinkCF6Replace with a reflink to the keeper (ZFS block_cloning)
DeleteDF8Delete (to quarantine)
Selected*Space / InsertAn ephemeral batch (for the m layout)

Space on an already-marked file removes the mark (by default it sets Selected, but if there was a K/H/C/D it removes it).

Insert is the same as Space, for batch marking in the style of classic two-panel file managers.

The semantics of the actions (what exactly hardlink/reflink/delete do, and why a hardlink is better than a delete) — see §08 Actions.

F-keys — first layer

This is what is drawn on the footer. With no modifiers:

F-keyAction
F1 or ?Keyboard help (overlay)
F2Scan the active panel's directory
F3Info about the file under the cursor (the FileInfo overlay)
F4Compute the hash of the file under the cursor (in the background)
F5Mark as Hardlink
F6Mark as Reflink
F7Mark as Keeper
F8Mark as Delete
F9Menu (overlay)
F10Exit
F11 or xApply the marked actions (the confirmation overlay). Also in the F9 menu — most terminals eat F11
F12Sessions and scan results (the ResumeScan overlay + the session list)

F-keys — second layer

This is enabled by holding Shift when pressing an F-key OR by the prefix key ` (grave accent) for the one next F press. The footer is highlighted in yellow when the prefix is armed.

Why two mechanisms: the Proxmox web shell terminal (xterm.js) does not pass Shift+F — the ` prefix is intended for it.

Key (Shift+F / ` F)Footer labelAction
F1SyncSynchronize all panels to the active panel's directory
F2CompareCompare the files and folders between panels
F3+PanelAdd a panel (≤ 4)
F4-PanelRemove a panel (≥ 2)
F5RootChange the active panel's root (across datasets)
F6SizeRecompute the directory size (in the background)
F7, F8—Unassigned
F9WizardOpen the scan configuration wizard (ScanConfig)
F10, F11—Unassigned
F12BoardTriage Board — the screen for laying out across 4 receivers (§09)

The prefix is cleared:

  • automatically after any key press;
  • by pressing ` again (toggle);
  • by an F-key (the second layer handles it and clears).

The same prefix followed by the digit row reaches the FIRST layer, for terminals that keep an F-key for themselves (F10 = menu, F11 = fullscreen in most of them): ` 1…9 = F1…F9, ` 0 = F10, ` - = F11, ` = = F12. Execute also has the letter alias x. See §13 Troubleshooting.

The F9 menu (14 items)

┌─ Menu — F9 ────────────────────────────────────────────────────────────┐
│  1. Scan the active panel's directory                                  │
│  2. Configure and start a scan…                                        │
│  3. Sessions and scan results…                                         │
│  4. Execute marked actions (F11 or x)                                  │
│  5. Clear all marks                                                    │
│  6. Reload scan data                                                   │
│  7. Change panel mode (v)                                              │
│  8. Synchronize panels (Shift+F1)                                      │
│  9. Compare panels (Shift+F2)                                          │
│  10. Add a panel (Shift+F3)                                            │
│  11. Remove a panel (Shift+F4)                                         │
│  12. Change panel root (Shift+F5)                                      │
│  13. Recompute directory size (Shift+F6)                              │
│  14. Keyboard help                                                     │
│                                                                         │
│  ↑↓ select  Enter apply  Esc cancel                                    │
└────────────────────────────────────────────────────────────────────────┘
KeyAction
↑ / ↓Cursor over the items
EnterApply the selected item
Esc or F9Close the menu without an action

Item 2 = Shift+F9, item 3 = F12, item 4 executes the marked actions (F11 or x), item 5 clears every saved mark of the scan after a question (see "Clear all marks" below). Items 7–13 duplicate the hotkeys named in their own labels (for those who do not yet remember them); item 6 has no key of its own, and item 14 is the help screen.

Overlays

Besides the menu there are four more modal overlays:

F11 confirmation (Overlay::Confirm)

┌─ Confirmation — F11 ───────────────────────────────────────────────────┐
│   Summary     Commands                                                 │
│                                                                         │
│   Actions to be executed: 9                                            │
│   By type: delete 2 · hardlink 7                                       │
│   guaranteed after quarantine purge: 232.0 MiB                         │
│                                                                         │
│   DELETE    /tank/junk/duplicate.bin                                   │
│   DELETE    /tank/junk/duplicate-2.bin                                 │
│   HARDLINK  /tank/dup/IMG_4421.HEIC                                    │
│   HARDLINK  …/old-copy/IMG_4421.HEIC                                   │
│   HARDLINK  /tank/dup/IMG_4422.HEIC                                    │
│   … and 4 more                                                          │
│                                                                         │
│   A ZFS snapshot for rollback is created before changes.               │
│                                                                         │
│   [Tab] tab  [S] save .sh  [Y] execute  [N]/[Esc] cancel               │
└─────────────────────────────────────────────────────────────────────────┘

Summary reports the plan by composition, not just by total: the By type line and up to five quoted targets. "Actions: 3" reads the same whether F7 or F8 landed on the copy, so the kinds and the paths are what catch a mis-marked batch before Y. Long paths are elided from the left so the file name stays. A short terminal gives things up in order — first the quoted paths, then the spacing, then the snapshot note, then the size — so that the count, the composition, the … and N more and the [Y]/[N] hint are always on screen.

The Commands tab shows the plan's shell script and scrolls: the script of a large plan runs to thousands of lines, and the whole point of an audit view is that it can be read to the end. The overlay title carries the position as lines X-Y of N, or no script lines when there is nothing to show.

┌ Confirmation — F11 · lines 105-112 of 118 ──────────────────────────────┐
│   Summary    Commands                                                   │
│                                                                         │
│ # 4. Actions: 3 total.                                                  │
│ dedcom_failed=0                                                         │
│ # reflink (clone beside it, then the file to quarantine): /tank/dup/copy│
│ dedcom_reflink '/tank/dup/copy1.bin' '/tank/dup/orig.bin' '/tank/.dedcom│
│ # reflink (clone beside it, then the file to quarantine): /tank/dup/copy│
│ dedcom_reflink '/tank/dup/copy2.bin' '/tank/dup/orig.bin' '/tank/.dedcom│
│ # reflink (clone beside it, then the file to quarantine): /tank/dup/copy│
│ dedcom_reflink '/tank/dup/copy3.bin' '/tank/dup/orig.bin' '/tank/.dedcom│
│                                                                         │
│  ↑↓ · PgUp/PgDn · Home/End — scroll                                     │
│  [Tab] tab  [S] save .sh (whole script)  [Y] execute  [N]/[Esc] cancel  │
└─────────────────────────────────────────────────────────────────────────┘
KeyAction
↑ / ↓Scroll the script one line (Commands tab)
PgUp / PgDnScroll a screenful, one line of overlap
Home / EndFirst / last window of the script
TabSwitch the tab: Summary ↔ Commands (the full shell script)
SSave the plan as a .sh (audit trail; manual execution is possible)
YExecute — start applying
EnterNothing. Applying is destructive, so it costs a deliberate Y
N / EscCancel

S always writes the whole script, whatever part of it is on screen. On a window too small for both hint lines the scrolling hint goes first — the [Y]/[N] line stays.

Enter does not execute. It used to be a synonym for Y, which made the one irreversible step in the tool reachable by the key people press to dismiss a dialog they have not read. Enter is now ignored here: the confirmation stays open and the plan is untouched.

F3 file info (Overlay::FileInfo)

┌─ File — F3 · Esc to close ─────────────────────────────────────────────┐
│  Path:    /tank/media/photo/IMG_3120.HEIC                             │
│  Size:    3.6 MiB                                                     │
│  Mtime:   2024-08-15 14:23:11                                         │
│  Device:  0x42 (zfs:tank)                                             │
│  Inode:   12345678                                                    │
│  Hash:    a3f5...  (from the last scan)                               │
│  Duplicates: 4 (including this one)                                   │
└─────────────────────────────────────────────────────────────────────────┘
KeyAction
Enter / Esc / F3Close

Resume — F2 (Overlay::ResumeScan)

On F2 (scan the active panel), if this root already has an unfinished or finished session, it asks what to do with it:

┌─ Scan roots — F2 ──────────────────────────────────────────────────────┐
│   Root: /tank                                                          │
│                                                                         │
│   Unfinished scan: 2026-05-20 14:15  (47% by volume, 1.2 TiB)         │
│   Last completed: 2026-04-12 09:23  (12,437 groups)                   │
│                                                                         │
│   [R]/[Enter] resume                                                   │
│   [O] open completed                                                   │
│   [N] new scan                                                         │
│   [Esc] cancel                                                         │
└─────────────────────────────────────────────────────────────────────────┘
KeyAction
RResume the unfinished session (if any)
OOpen the result of the last completed scan
EnterEquivalent to R, or O if there is no unfinished session
NIgnore everything, start a new scan
EscCancel (return to the commander without a scan)

The check of saved scans runs in the background, as do the file info of F3 and the plan of F11. If something that takes the keys is in front when the answer arrives — the F9 menu or another F-key window, help, the Triage Board, a move waiting for its target panel — or you have left the commander, the answer opens nothing and starts no scan. Close what is in front and press the same key again. The status line says what arrived, except while a move waits for its panel: that line is the move's prompt then.

Opening a result with O (or Enter, when nothing is left to resume) takes a moment as well. If a window, the Triage Board or a waiting move is in front when it is ready, or you have left the commander, the scan opens but the screen stays where it is, and the status line names the scan: F12, then Enter on it in the list of scans shows its groups. Help does not hold it back — the groups open under it.

Clear all marks — F9, item 5 (Overlay::ClearMarks)

The F11 plan is built from every mark the database holds for the scan, marks set in an earlier session or in the classic interface included, and a files panel shows only the marks set while it was open. So item 5 clears them in the database, all of them, after a question that names the scan:

┌ Clear all marks — F9 ────────────────────────────────────────────────┐
│ Clear every saved mark of scan #1, keepers included?                 │
│ 1 file is marked for an action.                                      │
│ Marks no panel shows go too: the F11 plan is built from all of them. │
│                                                                      │
│ [Y] yes · [N] no                                                     │
└──────────────────────────────────────────────────────────────────────┘

The count is of the files marked for an action; keepers are not in it and go too. When that count is not known yet, the line is left out. On Y the status line reads Marks cleared: N, N being the marks the database held, and no panel or group shows a mark of that scan any more. Marks of other scans stay in the database; a panel that still held one drops it. The selection made with Space or Insert is not a mark and stays.

The item is refused in read-only mode, without a loaded scan, while a mark is still being saved or the marks are still being cleared, and while something that would open a window over the question or install another scan under it is still on its way — a plan being built (F11), a check of saved scans (F2), a file's info (F3), a scan opening, the lookup of a panel's scan, auto-select. The status line says which; ask again when it is done. If a scan is opened while the question is open, the same one again or another, or the database file is replaced under it, the question closes and nothing is cleared.

KeyAction
YClear every saved mark of the scan
N / EscClose; nothing is cleared
EnterNothing — as in F11, it costs a deliberate Y

Side-by-side comparison (,)

The , (comma) key turns the CompareMode::SideBySide mode on/off for neighbouring panels in the Files/DirsOnly views:

┌─ /tank/photos · files ──┐  ┌─ /tank/photos-bak · files ──┐
│ = IMG_3119.HEIC          │  │ = IMG_3119.HEIC               │
│ ≈ IMG_3120.HEIC          │  │ ≈ IMG_3120.HEIC               │
│ ~ IMG_3121.HEIC          │  │ ~ IMG_3121.HEIC               │
│ + IMG_3122.HEIC          │  │                                │
│                          │  │ + IMG_extra.HEIC               │
└──────────────────────────┘  └────────────────────────────────┘

Match glyphs:

  • = — identical (the same hash)
  • ≈ — similar (close size/date)
  • ~ — differs
  • + — present only in this panel

Useful for an eyeball comparison of two "versions" of a directory — backup vs original.

Triage Board — laying out across 4 receivers

A separate screen for manually distributing files. It opens with Shift+F12 (or "start the layout" — the m key + a digit 1–4). This is not deduplication — it is a "I brought a file here and sorted it into bins" tool. Details — §09 Triage Board.

Other actions

KeyAction
m / MStart the layout: select files → a digit 1–4 = the receiver
u / UUndo the last layout move (Undo)
q / QExit

What's next

Published from docs/manual/05-commando.md at v0.9.2 · last changed 2026-09-28