sugarcraft / super-candy
Dual-pane terminal file manager built on the SugarCraft stack. Inspired by superfile and Midnight Commander. Navigate two directories side-by-side, sort by name / mtime / size, multi-select, delete with confirmation, swap focus with Tab.
Requires
- php: >=8.1
- sugarcraft/candy-core: @dev
- sugarcraft/candy-sprinkles: @dev
Requires (Dev)
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2026-05-19 01:56:45 UTC
README
SuperCandy
Dual-pane terminal file manager built on the SugarCraft stack — port of yorukot/superfile, with the Midnight Commander look.
┌────────────────────────────────────┐ ┌────────────────────────────────────┐
│ /home/alice [name-asc] │ │ /var/log [mtime-desc] │
│ ────────────────── │ │ ────────────────── │
│ ▸ ../ DIR │ │ ../ DIR │
│ Documents/ DIR │ │ ▸✓ syslog 240KB │
│ Downloads/ DIR │ │ auth.log 12KB │
│ .config/ DIR │ │ Xorg.0.log 4.0KB │
│ notes.md 12KB │ │ │
│ todo.txt 512B │ │ │
└────────────────────────────────────┘ └────────────────────────────────────┘
Tab swap · ↑↓ jk move · Enter open · ← h up · space select · s sort · . hidden · d delete · r refresh · q quit · / search · t tabs · u undo
Run it
composer install ./bin/supercandy [LEFT_DIR] [RIGHT_DIR]
Default: left pane = current directory, right pane = $HOME.
Keys
| Key | Action |
|---|---|
Tab |
Swap focus between panes |
↑ / k |
Move cursor up |
↓ / j |
Move cursor down |
Home / g |
Top of listing |
End / G |
Bottom of listing |
Enter / → |
Open directory (or no-op on a file) |
← / h |
Go up one directory |
Space |
Toggle selection on the entry under cursor + advance |
s |
Cycle sort order (name → mtime → size, asc / desc) |
. |
Toggle hidden-file visibility |
d |
Delete (selection or cursor); requires y confirm |
r |
Refresh active pane |
q |
Quit |
/ |
Start search mode; type to filter; Enter to open |
Escape |
Exit search mode |
t |
Duplicate current tab |
Ctrl+w |
Close current tab |
Ctrl+Tab |
Cycle to next tab |
Ctrl+Shift+Tab |
Cycle to previous tab |
u / Ctrl+z |
Undo last delete operation |
Architecture
The whole transition layer is pure — filesystem I/O is injected as a Closure(string $path): list<Entry> so every transition is unit-testable without tmp dirs or stat fixtures.
| File | Role |
|---|---|
Entry |
Value object: name, isDir, size, mtime, isLink, isHidden |
Sort |
Enum (NameAsc/NameDesc/MtimeAsc/MtimeDesc/SizeAsc/SizeDesc) + comparator |
Pane |
One pane: cwd, entries, cursor, selection set, sort, showHidden |
ConfirmState |
Pending-confirmation enum (None / DeleteSelected) |
Manager |
SugarCraft Model — orchestrates two panes, handles all keys + confirm gate |
FsLister |
Default lister: scandir + lstat against the live filesystem |
Renderer |
Pure view function — two pane boxes side-by-side + status line |
Test plan
- 36 tests / 65 assertions
- Pure-state coverage:
Entry(size formatting, parent sentinel),Sort(every order × dirs-first × cycle),Pane(open / navigate / move / select / sort / hidden toggle / parent-path / join) Managerintegration: Tab swap, key dispatch per pane, confirm gate (darms,yconfirms, anything else cancels), refresh status
Demos
Navigation
Search
Multi-select and delete
Tab management
Sort cycling
Undo delete
Hidden-file toggle
Status
Phase 9+ entry #20 — first cut. Read + delete are wired; search, tabs, and undo are fully implemented; copy / move / rename / new-dir are obvious next steps. Everything underneath them (the pure-state transition layer) is already in place.






