Getting started¶
The idea in three sentences¶
muxget is a front end. It spawns aria2c, yt-dlp and wget, reads what they
print, and handles the queueing, scheduling and bookkeeping around them. There
is no daemon and no background service: when muxget exits it kills the processes
it started, so a transfer only runs while you are watching it, and everything
it knows is written to a state file, so the next launch picks up where this one
stopped.
Three things worth having in mind:
- A download is a row. It has a url, a queue, a status and a percentage. It keeps its identity when you pause it, retry it, reorder it, or restore it from a previous run.
- A queue is a lane with a slot count. Each queue starts its own downloads up to its own limit, independently of every other queue. A busy lane never blocks another one.
- A backend is an external program. Which one runs is decided from the url, or by a rule you wrote, or by a crawl. muxget knows how to build its command line and how to read its progress. The rest is that tool's job.
The screen¶
header muxget │ queue │ running │ queued │ done │ failed │ speed │ dir
sidebar queues, then filters
table the current queue, filtered
sparkline how fast everything is going, last two minutes
details the selected row in full
footer a few keys, then the last message, `?` has the rest
The layout is responsive, and panels are dropped rather than squeezed:
| below | what goes |
|---|---|
| 90 columns | the queue and filter sidebar |
| 64 columns | the details panel |
| 100 / 74 columns | footer key hints thin out |
| 20 rows | the throughput sparkline |
The table¶
Columns appear as width allows: icon, name, progress bar, percent, then total size, rates and status. The size is whatever the backend reported and stays blank until it reports one. A video that yt-dlp fetches as separate video and audio streams shows the stream it is on, so the number changes once when it moves to the audio. aria2c reports the whole file throughout. A total nobody knows yet is not worth guessing from the percentage.
Rows are zebra striped. The name is the file name once a backend reports one, and the url until then.
Status icons¶
| plain | nerd font | means |
|---|---|---|
· |
queued | waiting for a slot |
▶ |
running | a process is working on it |
⏸ |
paused | the process is stopped, its slot is free |
✓ |
done | finished successfully |
✗ |
failed | the tool exited with an error |
■ |
cancelled | you stopped it, the row stays |
Nerd font glyphs are off by default. Turn them on in the general tab of S if your terminal font has them.
Filters¶
Tab cycles the filter, which decides which rows the table shows:
| filter | shows |
|---|---|
| all | everything in this queue |
| active | running, queued and paused |
| done | finished |
| failed | failed and cancelled |
The filter is a view, not a state: hidden rows keep downloading. The selection always lands on a row that is actually on screen.
Moving around¶
J / K or the arrow keys move the selection, [ / ] switch queue. Two-key sequences group the less common commands: press G for queue commands or I for item commands and a menu shows what the second key can be. Anything not in the menu cancels the sequence, as in vim. Q or Shift+Z Shift+Z quits.
The list takes vim's movements. J and K step, GG and Shift+G jump to the ends, Ctrl+D and Ctrl+U move half a screen, Ctrl+F and Ctrl+B a whole one, measured against the rows the list can actually show, so a taller terminal pages further.
Digits typed before a movement repeat it: 5j is five rows down, 12G is the
twelfth row. The count belongs to the command right after it and is forgotten
otherwise, so a stray number cannot surprise the next keypress. Everything is
clamped to the list and to the current filter, so a movement never lands on a
row that is not on screen.
The mouse works too: click a queue, a filter or a row to select it, and scroll over the queue list to change queue, over the table to move the selection. While a dialog or the settings panel is open it owns the keyboard, and the mouse is ignored so a stray click cannot act behind the popover.
Selecting rows¶
Space marks the row under the cursor, Shift+M marks everything between the last mark and the cursor, and Shift+A marks every row on screen, or clears them all if they already are. Marked rows carry a bar in the left margin and the table title counts them.
Every per-row operation then acts on the selection: P pauses or resumes,
X stops, D deletes, it retries, iR deletes with the files. With
nothing marked they act on the cursor row alone, so the selection is something
you opt into.
Marks are download ids rather than row numbers, so they survive sorting, filtering, queue switching and the rows moving under them. An operation clears the selection when it finishes, since it described rows that have just changed or gone.
Typing in a field¶
Every field in muxget, the add form, the settings panel, every dialog, takes the same editing keys, the ones readline gave a shell and a browser address bar:
| key | action |
|---|---|
| Left Right | move the caret a character |
| Ctrl+Left Ctrl+Right or Alt+Left Alt+Right | move it a word |
| Home / End, or Ctrl+A / Ctrl+E | start / end of the line |
| Backspace / Del | delete the character behind / ahead |
| Alt+Backspace | delete the word behind |
| Ctrl+W | delete back to the last space |
| Alt+Del | delete the word ahead |
| Ctrl+U / Ctrl+K | delete back to the start / on to the end |
A word ends at anything that is not a letter or a digit, so Alt+Backspace in a url takes one path segment at a time. Ctrl+W is the shell's version, back to the last space, which on a url takes the whole thing.
Moving to another field puts the caret at the end of what is already in it.
Next: downloading things.