Copal
copal The installer, on the machine itself: re-run any stage, update Copal, and see what is installed.
Copal · Copal's own · stage 3 · Move the root filesystem onto the card, or a disk of its own
On Copal: Stage 3 leaves this copy on every Copal machine, so the whole install -- eighteen stages -- can be re-run, one stage or all of them, and updated from the repository without the Mac.
Use
With no arguments it shows the stage menu. --stage N re-runs chosen stages; -U updates Copal's scripts from the repository (or from a local checkout); --check says whether an update exists. Updating changes what the stages will do; it does not run them. copal fleet is the fleet console.
Examples
copalthe stage menu
copal --checkis there a newer Copal?
doas copal -Uupdate from the repository
doas copal --stage 17re-run one stage (the desktop)
doas copal --stage 12,18 --autore-run two, answering for you
doas copal -U --from ~/code/copal && doas copal --stage 17 --autotest a local change
copal --versionwhat is installed, and from where
copal fleet lsthe fleet console: what is out there
Options
--stage N,...- run only these stages (add --auto to answer their questions)
--auto- every stage, unattended, resuming across reboots
-U [REF]- update from the repository; REF a branch, tag or commit
-U --from PATH- update from a checkout on this machine
--check [REF]- whether an update is available; changes nothing
--version- the installed version and its source
fleet VERB ...- the fleet console, from the checkout in ~/code/copal
Notes
- Every stage is written to be run again: a re-run repairs or updates what it set up and leaves the rest alone.
- An update keeps the previous copy as
copal-init.sh.bak. -U REF pins a version: a tag or commit goes back to an older Copal.copal fleet runs tools/copal-fleet.sh from the checkout in ~/code/copal (or $COPAL_CHECKOUT), because the console needs the checkout around it. On the Mac or Linux host that holds the fleet's authority, make install-fleet in the checkout adds the same command.
See also copal-store, copal-config, copal-code
copal-apps Copal Apps: the window for browsing Copal's programs by shelf, installing them, and watching installs happen.
Copal · Copal's own · stage 18 · The Copal Store, and OpenShot compiled
On Copal: The graphical face of copal-store. It never installs anything itself and never needs root: Install opens a terminal running doas copal-store install, and the window follows the progress. At the full monty's first login it opens on the slideshow of the queued programs arriving.
Use
Open it from the menu or the command line. Shelves on the left, programs with their status in the middle, one program in full on the right: its picture, two sentences, where it comes from and how it installs. While an install runs, it shows each program arriving with three progress bars.
Examples
copal-appsthe shelves and programs
copal-apps gimpopened on one program
copal-apps --progressthe install running now, as a slideshow
copal-apps --followthe slideshow, only if something is installing
Options
ID- open on that program
--progress- the running install's slideshow: the run, the program, the step
--follow- the same, but only when an install is queued or running
Notes
- Everything it shows comes from copal-store (
copal-store rows, copal-store playbook ID) and the event stream it writes to /var/log/copal/events: the terminal and the window always agree. - Pictures are the gallery's, fetched once into
~/.cache/copal-apps; a program without one shows its icon. - It needs a desktop (GTK); on a console,
copal-store alone gives the same shelves as terminal menus.
See also copal-store, copal-install, copal-menu
copal-audio-start Start the sound server -- PipeWire, WirePlumber and the PulseAudio shim -- for this login.
Copal · Copal's own · stage 10 · Wireless, audio, capture and disks
On Copal: On Copal there is no systemd to start PipeWire per user, and it must not run as a system service. This starts the three parts once per session, skipping any already running, and does nothing at all on a machine without PipeWire.
Use
The i3 session runs it at startup. Run it by hand when a program says there is no sound server; it is safe to run again.
Examples
copal-audio-startstart whatever is missing
wpctl statusthen see the devices
tail $XDG_RUNTIME_DIR/copal-audio.logwhat the servers said
Options
Notes
- It starts
pipewire, then wireplumber (the session manager, which connects devices) and pipewire-pulse (so PulseAudio programs play), each only if installed and not already running for your user. - Their output goes to
copal-audio.log in $XDG_RUNTIME_DIR (or /tmp), which is cleared at reboot. - Stage 10 installs PipeWire and writes this; the i3 session's startup file is what calls it.
See also wpctl, pipewire, pactl
copal-autologin What tty1 runs instead of the login prompt when the desktop starts at boot.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Autologin without a display manager: getty skips the name, this logs the admin user straight in. It also raises the memory-lock and real-time limits audio programs want, which nothing else on Copal can do, because logins here do not go through PAM.
Use
You do not run it. Stage 4 offers to start the desktop at boot; saying yes writes this and points tty1 at it in /etc/inittab.
Examples
grep tty1 /etc/inittabis autologin on?
doas rm /etc/copal/autostart-desktop # stop the desktop starting itself
ls /etc/inittab.bakthe inittab from before autologin
Options
Notes
- The inittab line is
getty -n -l /usr/local/bin/copal-autologin; it runs login -f for the admin user, so no password is asked on tty1. That is the point, and also the cost: whoever is at the keyboard is in. - It sets
ulimit -l unlimited (locked memory, which keeps Ardour's and JACK's buffers out of swap) and ulimit -r 95 (real-time priority); the desktop inherits both. - After logging in,
~/.profile waits five seconds and runs copal-session; Ctrl-C in those seconds gives you a shell instead. - Deleting
/etc/copal/autostart-desktop stops the desktop starting at boot, but the autologin stays: tty1 logs in to a shell. Undoing that means putting tty1's getty line in /etc/inittab back.
See also copal-session, getty, ulimit
copal-bar Start the desktop's bar and widgets with whichever shell the machine has: quickshell, else waybar.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: The theme's bar is written for quickshell, which Alpine does not package, so waybar stands in. copal-bar is the one place that decides, and prefers quickshell: install it and the next login uses the real thing, with nothing else changed.
Use
The session starts it; you run it by hand only to restart a bar that has gone. It starts the bar and the desktop widgets.
Examples
copal-bar &start the bar again, after it crashed
pkill -x waybar; copal-bar &restart it after editing its config
Options
Notes
- The waybar configuration is in
~/.config/waybar; copal-theme rewrites its colours, so keep your own changes to layout and modules. - If neither shell is installed it says so where it will be seen, rather than leaving a desktop with no bar and no explanation.
See also copal-widgets, copal-theme
copal-build Compile the checkouts in ~/code and install what they make into ~/.local/bin, by the shape of each project.
Copal · Copal's own · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts
On Copal: "Built" should mean "installed": on PATH, in the menus, with a man page. copal-build reads each checkout's shape -- CMake, Cargo, Go, npm, or a cc65 Makefile -- and builds it the way that shape builds, so a fork or a project it has never heard of works the same.
Use
With no argument it builds every checkout in ~/code; name some to build only those. list shows each checkout's shape and whether what it made is on PATH.
Examples
copal-buildeverything in ~/code
copal-build staticstream ascittyjust these
copal-build listshapes, and what each made
copal-build clean birdshotdelete its build directory
Options
(none)- build every checkout
NAME...- build only these (directory names under ~/code)
list- each checkout, its shape, and the programs it made
clean NAME...- delete build/, native/build/ and target/; keep the checkout
-h, --help- the usage
Notes
- Programs go to
~/.local/bin, which is on PATH from ~/.profile. Each gets a menu entry, and, from its README, a man page in ~/.local/share/man (man ytq), by copal-readme-man. - It never modifies a tracked file, because that would make every later
git pull fail: npm uses ci where there is a lockfile, and a Plus/4 program uses its committed .prg and .d64 instead of recompiling. COPAL_BUILD_PLUS4=1 recompiles anyway (needs cc65). - Parallel jobs are the CPU count, capped at one per 512 MB of memory, so a small board does not swap.
copal itself is not built: it is a script (make redeploy in ~/code/copal). A checkout with none of the shapes is left alone.COPAL_CODE and COPAL_PREFIX change ~/code and ~/.local.
See also copal-code, copal-readme-man, cargo, cmake
copal-camera Open the camera application, whichever one this machine has.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: One answer to "the camera", asked from three places -- the Camera entry in copal-menu, Super+Shift+B on both desktops, and the camera role in a copal-desk layout. Birdshot first, from ~/code; then other camera programs.
Use
Run it, or press Super+Shift+B; it opens the first camera program it finds: birdshot's window, else birdshot's browser viewfinder, else another installed camera application. --which says which, and opens nothing.
Examples
copal-cameraopen the camera
copal-camera --whichprint the command it would run
CAMERA=cheese copal-camerause another program, once
Options
--which- print the command it would run; exit 1 if there is none
Notes
$CAMERA overrides the choice, as $BROWSER does for the browser: set it in ~/.profile.local and every place that opens "the camera" follows.- Birdshot is one of the checkouts stage 7 builds into
~/.local/bin; copal-camera looks there even when the session did not read ~/.profile.
See also birdshot, copal-desk
copal-center One window listing the whole catalogue, installed or not, with the action for each.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Super+Shift+C: the catalogue at a glance. It opens Copal Apps where that exists, and the store's own window where it does not.
Use
Open it with Super+Shift+C or by name. Each row is a program with its status and section; choosing one runs it if installed, or installs it.
Examples
copal-centerthe catalogue window
Options
Notes
- It is the older window of the two; Copal Apps (
copal-apps) is the richer one, and copal-center hands over to it where it is installed.
See also copal-apps, copal-store, copal-install
copal-clip One clipboard, one set of keys, every window -- with a history, and a bridge to the VM host.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Super+C, Super+X and Super+V copy, cut and paste in every program, terminal included, the way Cmd-C does on a Mac. It keeps a clipboard history, and in a VM shares the clipboard with the host.
Use
The desktop binds the keys; you rarely run it by name. From a shell, store puts text on the clipboard and show prints it, which makes it the pipe between the clipboard and commands.
Examples
echo hello | copal-clip storeput text on the clipboard
copal-clip showprint the clipboard
copal-clip show | wc -wuse it in a pipeline
copal-clip historypick an earlier entry (Super+Ctrl+V)
Options
copy / cut / paste- the Super+C / Super+X / Super+V actions
history- choose from the clipboard history
store- put stdin on the clipboard
show- print the clipboard
watch- record the history (the session starts this)
bridge- share the clipboard with the VM host (the session starts this)
Notes
- In a UTM or QEMU guest, copy and paste with the Mac works only while
copal-clip bridge and spice-vdagent are running; both are started from hyprland.conf. If it stops working, check those two first. - The history keeps the last 100 entries, in
~/.cache/copal/clipboard; delete that folder to clear it.
See also wl-copy, ytq
copal-code Keep the source checkouts in ~/code: clone what is listed, pull what is there, then build it all.
Copal · Copal's own · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts
On Copal: A Copal machine arrives ready to work on its own projects. The list of repositories lives on the boot partition, where you can edit it from any computer before the card is even booted; this makes ~/code match it, and hands over to copal-build.
Use
Run it as yourself, with no argument: it clones anything listed that is missing, pulls (fast-forward only) anything that is there, and builds. add and rm edit the list and need doas.
Examples
copal-codeclone, pull, build
copal-code listthe list, and what is on disk
doas copal-code add https://github.com/you/project
copal-codethen clone it, as yourself
doas copal-code rm projectoff the list; the checkout stays
COPAL_NO_BUILD=1 copal-codeclone and pull, build later
Options
(none), sync- clone what is missing, pull what is there, then copal-build
list- each listed repository, and whether it is cloned
add URL...- add to the list (needs doas)
rm NAME...- remove from the list (needs doas); keeps the checkout
path- where the list is
Notes
- The list is
copal-repos on the boot partition (/boot), one URL per line, # for comments. ~/code/copal, the repository the machine was built from, is always included and cannot be removed; repoint it with git remote set-url.- Cloning tries SSH first, without prompting, and falls back to HTTPS; a machine with no SSH key yet still gets its checkouts.
copal-guide code explains adding a key. - A pull never forces: a checkout with local changes is warned about and left alone. A directory in the way that is not a checkout is skipped.
- Machines installed before 24 September 2026 have the Yodacon builder under this name; running stage 7 again installs this one, and the builder as copal-yodacon.
See also copal-build, git, copal-guide
copal-config System settings for Copal: users, host name, time zone, keyboard, SSH, services, boot and storage.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: raspi-config's job, done with Copal's own tools: the settings a Pi owner changes, in one place, in a window on the desktop or in the terminal on a console.
Use
Run it; it opens a window where there is a display and terminal menus where there is not. Choose a screen, change a setting. Most settings write to /etc, so it asks for doas when it needs to.
Examples
copal-configthe settings, in a window or the terminal
copal-config --tuithe terminal menus, even on a desktop
Options
--tui- the terminal interface, even with a display
--help- the usage
Notes
- Its screens: users (add one, groups), hostname, timezone, keymap, ssh, services (what starts at boot), boot, storage, and about.
- Each screen uses the same tools a shell would --
setup-timezone, rc-update, copal-ssh -- so a change made here and one made by hand agree. - It works with GTK (yad), curses (dialog), or plain prompts, whichever the machine has.
See also copal-ssh, setup-alpine, rc-update
copal-debug Turn on Copal's debug collection: one folder, /var/log/copal, holding everything worth reading about a fault.
Copal · Copal's own · written on every run of the installer
On Copal: Off by default, because on a working machine the extra writes buy nothing. When something is wrong, one command gathers a snapshot of the machine and links to every relevant log in one place -- readable over SSH, or bundled into one file to send to someone.
Use
doas copal-debug on 1d starts collecting and switches itself off after a day. copal-debug alone says whether it is on and what it has gathered. bundle makes a .tar.gz to copy off the machine.
Examples
copal-debugon or off, and what is collected
doas copal-debug on 1dcollect for a day, then stop
doas copal-debug collectrefresh the snapshot now
doas copal-debug bundleone archive in /tmp, ready for scp
doas copal-debug offstop; keep what is there
doas copal-debug purgedelete the collection
COPAL_DEBUG=1 copal-startxdebug for one command only
Options
status- whether it is on, and what is in the folder (the default)
on [TIME]- start collecting; TIME (1d, 12h, 30m, or seconds) ends it
off- stop collecting, leave the folder
collect- refresh the snapshot
bundle- tar the folder, links resolved, into /tmp
purge- delete /var/log/copal
expire- switch off if the deadline has passed (cron runs this)
Notes
- The folder holds
sysinfo.txt (kernel, consoles, graphics, input, gettys, services, which Copal), dmesg.log, and links to the install transcript, the system log, Xorg's log and the last desktop session. A broken link is a finding: xorg.log pointing nowhere means X never started. COPAL_DEBUG=1 or =0 in the environment overrides the switch for one command. The switch itself is the file /etc/copal/debug.- With debug on, copal-startx keeps ten session logs instead of two.
See also copal-logs, copal-startx, copal-gpu
copal-desk Put the workspaces into a known shape in one step: editor, terminal, browser, each where it belongs.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Super+Shift+D. Muscle memory needs things in the same place, so a layout file names what opens on which workspace, and one key lays the desk out. Deliberately not an autostart: you can decline it on the morning you want an empty machine.
Use
Run it (or press Super+Shift+D) and it opens what the layout names on the workspaces it names, without pulling your eyes along. The default layout is code; others are files you can write.
Examples
copal-deskthe 'code' layout
copal-desk --listthe layouts on this machine
copal-desk --show codewhat a layout does, without running it
copal-desk musica layout of your own
Options
NAME- lay out that layout (default: code)
--list- the layouts available
--show NAME- print a layout without running it
Notes
- Layouts are
NAME.layout files in /usr/local/share/copal/layouts (Copal's) and ~/.config/copal/layouts (yours, which wins over a system one of the same name). - The
code layout: the editor and a terminal on 2, an agent on 3, the browser on 5, and an empty 1 to start from. - It works on both desktops: Hyprland places each window as it opens; i3 switches workspace first.
See also copal-camera, hyprctl
copal-desktop Choose which desktop takes the screen at the next login: Hyprland (Wayland) or X11.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: The choice is two settings that must agree: the word in /etc/copal/session, and whether X's setuid server is armed. Setting them in one command means they can never disagree -- and Wayland gets to disarm a root-privileged binary nothing is using.
Use
status (or no argument) shows what is set. wayland and x11 change it, and need doas; the change takes effect at the next login.
Examples
copal-desktopwhat is set, and whether X is armed
doas copal-desktop waylandHyprland next time
doas copal-desktop x11back to X11
Options
status- the session word, and the X server's state (the default)
wayland- Hyprland at the next login; X's setuid server disarmed
x11- startx at the next login; X's setuid server re-armed
Notes
wayland refuses, changing nothing, if Hyprland is not installed.- Disarming removes the setuid bit from
/usr/libexec/Xorg.wrap. Xwayland, which runs X programs inside Hyprland, is a separate binary and is not affected.
See also copal-session, copal-startx
copal-fleet A fleet machine's own half of the fleet: what it announces, what it reports, and whether it has been enrolled.
Copal · Copal's own · stage 16 · Join the named fleet, and announce it
On Copal: A Copal fleet is a set of machines on one LAN that trust one certificate authority, run from a console. Each machine needs a small, readable program for its side -- announcing itself, reporting its health, taking part in choosing the warden -- and this is it.
Use
copal-fleet alone says what this machine thinks it is: its fleet, role, tags, scene, and whether it is enrolled. The other verbs are mostly for the console and the services; facts and state are good for a quick look.
Examples
copal-fleetthis machine's view of itself
copal-fleet factshealth, one fact per line
copal-fleet statethe same, on one line
copal-fleet browsewhich fleet machines this one can see
copal-fleet logs all 2the warden's collected logs, two days
rc-service copal-fleet statusthe service that keeps the beacon fresh
Options
status- fleet, node, role, score, tags, scene, authority, enrolment (the default)
state- one line of facts, for the console
facts- id, versions, uptime, memory, temperature, card use, certificate days...
id- the node's name
role- node or warden (or the pinned role)
score- this node's score in the warden election
elect- recompute the role
beacon- rewrite the mDNS announcement
watch- elect and rewrite the beacon every 4 minutes (the service)
browse- the fleet machines visible from here
install-cert- install a host certificate read from stdin (root)
bus-key- this node's bus identity, made if needed
bus-users- write the bus membership from stdin (warden, root)
bus-config- rewrite /etc/nats/nats.conf (warden, root)
bus-address- where the bus is
bus-state- what this node's part of the bus is doing
logs ID|all [DAYS]- the logs the warden has collected, even for a dead node
-h, --help- the usage
Notes
- The fleet console is a different program on the operator's machine:
copal fleet (make install-fleet on a Mac or Linux host). It reaches this one through copal-fleet-exec. - The warden is chosen by a score every node computes and publishes; the highest announcing node takes the role.
role-pin in /etc/copal/fleet fixes a role by hand. - The settings are one file per field in
/etc/copal/fleet. Stage 16 installs the program and the copal-fleet service. - The announcement says a machine is there, never that it is trusted: only its certificate decides that.
See also copal-fleet-exec, copal-fleet-agent, copal-remote, avahi-browse
copal-fleet-agent A fleet machine's standing connection to the fleet's message bus: presence, health and commands, all the time.
Copal · Copal's own · stage 16 · Join the named fleet, and announce it
On Copal: SSH answers when asked; the bus keeps the console's wall live without asking. The agent announces the machine, publishes its state as it changes, and runs commands that arrive on the bus -- through copal-fleet-exec, the same checked list SSH uses, so the bus can never do more than SSH can.
Use
You do not run it; OpenRC does, as the unprivileged copal-fleet account. Check on it with rc-service. --self-test runs its built-in checks without touching the network.
Examples
rc-service copal-fleet-agent statusis it running?
doas rc-service copal-fleet-agent restart
copal-fleet-agent --self-testits own checks
Options
--self-test- run the built-in checks and exit
Notes
- It publishes
hello every 10 seconds, the node's state on change (at most every 5 seconds), new lines of /var/log/copal-fleet.log, and an acknowledgement for every command it ran. - With no warden (and so no bus), it waits and tries again; that is normal during a handover, and SSH keeps working meanwhile.
- On the warden it also collects every node's log lines, so the logs of a machine that has died can still be read (
copal-fleet logs). - It publishes its own uptime, so the console can tell "the machine is up" from "the agent is alive".
See also copal-fleet, copal-fleet-exec, rc-service
copal-fleet-exec The only thing the fleet console's logins can run: a short, fixed list of verbs, each checked, each logged.
Copal · Copal's own · stage 16 · Join the named fleet, and announce it
On Copal: This is the fleet's security boundary. sshd sends every login by the copal-fleet account here, with no shell, no terminal and no forwarding, and what arrives is matched against a list of verbs rather than run as a command. A verb not on the list is refused and logged -- there is no pass-through.
Use
You do not run it; sshd does, as a forced command, with the console's request in SSH_ORIGINAL_COMMAND. The fleet agent hands bus commands to it the same way. Read it to know exactly what the console can do to a machine.
Examples
copal fleet run uptimefrom the console: one verb, every node
copal fleet run message Please stand back
doas tail /var/log/copal-fleet.logon a node: what was asked, and refused
Options
state, status, facts, score, id, uptime- reports; nothing changes
beacon- rewrite the mDNS announcement
power off|reboot- shut down or restart
snapshot restore- restore the node's snapshot (if it has copal-snapshot)
scene apply NAME- record the scene name; applying it is Ansible's job
bus key|users|state- the node's bus identity, membership (warden), state
logs ID|all [DAYS]- the warden's collected logs
log tail [N]- the last lines of this node's fleet log
remote start|stop|status- share the screen, bounded (see copal-remote)
message TEXT- put a sentence on the screen (see copal-notify)
Notes
- A message is at most 200 characters of letters, digits, spaces and
. , ! ? : and -: no quotes, brackets or slashes, so nothing in it can be read as markup or shell syntax. - A scene name is lowercase letters, digits and dashes.
- Every request is logged with the caller's address to
/var/log/copal-fleet.log; refusals are marked REFUSED. - Adding a verb means editing this file, and nothing else can add one: the bus agent parses no verbs of its own.
See also copal-fleet, copal-fleet-agent, copal-remote, copal-notify, sshd
copal-fonts Install Copal's font sets -- coding, console, IBM PC, web documents -- and set the text console's font.
Copal · Copal's own · stage 12 · The application catalogue
On Copal: Fonts in groups rather than one by one: the coding faces (with Nerd Font symbols for prompts), the console fonts, the classic IBM PC faces, and the metric-compatible set that makes a .docx look right. Stage 12 installs coding, console and ibmpc by default.
Use
With no arguments it shows what is installed, group by group. install adds a group; console sets the font of the text console (the one before the desktop, and after Ctrl-Alt-F2).
Examples
copal-fontswhat is installed, by group
copal-fonts list codingwhat a group contains
doas copal-fonts install webthe document fonts (about 120 MB)
doas copal-fonts install coding-extraIosevka and the large Nerd cuts (~1.9 GB)
doas copal-fonts consolethe console fonts available
doas copal-fonts console ter-v24nset one
Options
install GROUP...- coding, console, ibmpc, web, coding-extra, or all
list [GROUP]- a group's contents, and what is on disk
console [NAME]- list, or set, the text console's font
licences- where the fonts' licence files are
Notes
web is not installed by default: it matters only when a document from elsewhere looks wrong, and it is large. Install it when that happens.- Installing a group again only fetches what is missing.
See also starship, oh-my-posh
copal-gpu Say whether the desktop is drawn by the GPU or the CPU, layer by layer, and what to do about it.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: A slow desktop is usually software rendering, and the reason can be at any of four layers: the kernel's device, the host's VirGL offer, the compositor's renderer, or Mesa's. This checks each and reports the first fault only, because one fault makes every layer above it look wrong too.
Use
Run it inside the desktop. It lists what it found at each layer and ends with a verdict and, when there is a fault, the fix.
Examples
copal-gputhe report
copal-gpu >/dev/null; echo $?just the verdict, for a script
Options
Notes
- The exit status is the verdict: 0 accelerated, 1 working but drawn on the CPU, 2 cannot tell yet (X has not run since boot).
- Under Hyprland the answer is the
Renderer: line in Hyprland's log: llvmpipe means software. Under X it reads the Xorg log for the driver and glamor, then asks glxinfo -B (package mesa-demos). - In a UTM virtual machine, 3D is the host's decision: "-virgl" in the kernel's messages means the display device offers none, and the fix is the VM's display setting (virtio-ramfb-gl), not anything inside.
- On a Raspberry Pi, no DRM device and the framebuffer path are expected.
See also glxinfo, dmesg, copal-debug
copal-gui The other menu, Linux Mint's Cinnamon style: favourites, categories, icons and search, for the mouse.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Super+A. The mouse's menu beside copal-menu's keyboard one: hover a category to switch to it, hover a program to read about it, click to run. It sits over the screen as a layer, on the theme's own menu colours.
Use
Press Super+A (again to close). Categories on the left switch on hover, after a short pause; programs on the right describe themselves at the foot as you hover them; a click runs one. Type to search. Right-click a program to add or remove it from the favourites column.
Examples
copal-guiopen the menu, or close it if open
copal-gui --listevery entry: section|name|desktop id
Options
--list- print section|name|desktop-id for every entry, and exit
Notes
- Scrolling by the edges: rest the pointer in the strip at the top or the bottom of the list and it scrolls at a steady pace; the rows in between stay still, so a click lands on what you aimed at. The wheel works as usual.
- The favourites are kept in
~/.config/copal/gui-favourites, one per line: edit it, or right-click in the menu. - A click anywhere outside the menu closes it.
See also copal-menu, copal-apps
copal-guide Read Copal's plain-text guides, on the machine, with no network: tmux, nvim, languages, radio and more.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: The tutorials that come with Copal -- how the editor is set up, which languages this board has, software radio, the small web -- kept in /usr/local/share/copal/guides and opened by name. Super+/ (or Super+F1) opens the desktop's key guide.
Use
Without a name it lists the guides and asks which; with a name it opens that guide in the pager.
Examples
copal-guidethe list, then a choice
copal-guide nvimthe editor, from nothing to useful
copal-guide languageswhat this board has, and why
copal-guide radiosoftware-defined radio
copal-guide small-webGemini and Gopher
Options
NAME- open that guide (the file's name without .txt)
Notes
- The guides are plain text files in
/usr/local/share/copal/guides; less or grep reads them as well. - The stage that installs a feature writes its guide, so the list grows with what the machine has.
See also man, tldr
copal-halt End the session, and the machine, in one step: shut down, restart or log out, asking first.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Super+Shift+P and Session in the menu both run it. It closes the desktop properly first, so programs are asked to quit, then powers down -- from a terminal, a console or SSH alike, without typing the root password.
Use
With no argument it asks, then shuts down. reboot restarts, logout leaves the desktop and keeps the machine running. -y skips the question.
Examples
copal-haltshut down (asks first)
copal-halt rebootrestart
copal-halt logoutleave the desktop
copal-halt -y rebootrestart without asking
Options
(none)- shut down, after asking
reboot- restart
logout- end the desktop session only
-y, --yes- do not ask
-h, --help- the usage
Notes
- It needs no password: a narrow doas rule,
zz-copal-halt.conf, lets your account run only this. That rule is named to sort after the general wheel rule, because in doas the last match wins. - Inside i3 it closes the session first, so unsaved work gets its prompt before the power goes.
See also doas, rc-service
copal-install Install packages from the menu's Install branch, in a terminal that stays open to say how it went.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: What the menus run when you choose a program you do not have yet. It installs the packages, then -- where Copal Apps is present -- their man pages, optionals and group access, and refreshes the menu so the program is there the next time it opens.
Use
You rarely type it: the menus open a terminal running it. By hand, name the packages; a name ending @testing comes from Alpine's testing repository, and one ending @flathub from Flathub.
Examples
doas copal-install htopone package
doas copal-install maxima@testingfrom the testing repository
doas copal-install com.brave.Browser@flathuba Flatpak (~500 MB runtime first)
Options
PKG...- Alpine packages to install
NAME@testing- from edge/testing (the repository tag is added if needed)
NAME@flathub- a Flatpak from Flathub
Notes
- The window waits for Enter at the end, so a failure's message can be read: the usual causes are no network, or a package this board's architecture does not have.
- It needs root, and says so: run it with doas.
- On a RAM-resident system it reminds you to
lbu commit; an installed Copal machine does not need that.
See also copal-store, copal-menu, apk
copal-launcher Open the program launcher -- whichever this machine has: Copal's menu, wofi, or dmenu.
Copal · Copal's own · stage 17 · Hyprland and the Antiquity theme
On Copal: What the theme's launcher key runs. Linux Antiquity names its own launcher, which is not packaged for Alpine; this hands the key to copal-menu, falling back to wofi or dmenu.
Use
Press the launcher key (Super+Space) or run it; it opens the first launcher it finds.
Examples
copal-launcherthe menu, as the key opens it
Options
Notes
- The order is copal-menu, then
wofi --show drun, then dmenu_run; if none is installed it says so and exits.
See also copal-menu, copal-gui
copal-logflush Copy the logs kept in RAM down to the card, and back up at boot -- so they survive, with few writes.
Copal · Copal's own · stage 15 · What wears a card, logs, a read-only root
On Copal: An SD card wears with every small write. With /var/log in RAM, this chooses when to write: one complete copy each hour and at shutdown instead of a stream of appends. It is log2ram's design, in a few lines of shell.
Use
You do not run it by hand. It runs only if stage 15's "flush periodically" was chosen: hourly from cron, at shutdown, and at boot to restore.
Examples
doas copal-logflush savecopy the logs down now
ls /var/log.persistthe copy on the card
Options
save- /var/log (RAM) -> /var/log.persist, then sync (the default)
restore- /var/log.persist -> /var/log (at boot)
Notes
- It does nothing unless
/var/log is a tmpfs, so it cannot double the writes on a machine logging straight to the card. - A power cut loses up to an hour of logs; a clean shutdown loses none.
- A log deleted from RAM is deleted from the copy too, by rsync's
--delete where rsync is installed, and by a prune after cp -a where it is not. - The hooks are
/etc/periodic/hourly/copal-logflush and /etc/local.d/copal-logflush.start and .stop.
See also copal-logs, rsync
copal-logs Find the logs that matter on a Copal machine, read them, and clear out the old ones.
Copal · Copal's own · written on every run of the installer
On Copal: The evidence for a desktop that will not start is in a file most people never find. This lists the desktop sessions, the install transcript and the system logs with their sizes, opens the one you want in a pager, and cleans up only what is safe to lose.
Use
With no argument it shows what exists and what it costs. x opens the newest desktop session log, errors picks out its error lines, install opens the install transcript.
Examples
copal-logswhat logs there are
copal-logs xthe last desktop session, in less
copal-logs x 2the one before it
copal-logs errors(EE), (WW) and error lines only
copal-logs installwhat the install stages did
copal-logs cleanremove old sessions and stale .bak files
Options
status- what exists, and its size (the default)
x [N], session [N]- a desktop session log; N counts back, 1 the newest
list- every desktop session log, newest first
errors- the error and warning lines from the newest session
install- the install transcript (copal.log on the boot partition)
clean- delete session logs beyond what copal-startx keeps, and stale .bak files
clean --all- the same, and rotate the install transcript to .1
Notes
- The session logs are the X11 desktop's, written by copal-startx into
~/.local/state/copal: the latest two, or ten while copal-debug is on, which is also what clean keeps; a Hyprland session keeps its own log under $XDG_RUNTIME_DIR/hypr, which this does not read. clean removes /etc/inittab.bak, /boot/copal-init.sh.bak and /etc/apk/world.bak, but only where the original is beside them. Run it with doas for those.status says whether /var/log is in RAM (lost at reboot unless the flush is on) or on disk.
See also copal-startx, copal-debug, copal-logflush, less
copal-morse Send text as Morse code, drill yourself on it, or print the table.
Copal · Copal's own · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts
On Copal: Alpine packages no Morse program at all, and Copal is a radio amateur's machine too. This one is written for timing: it builds the whole message as one sound file with sox, so the rhythm is exact even on a slow board where starting a program per beep would ruin it.
Use
Give it text and it plays and prints the code. -d is the drill: it sends five random letters, you type what you heard.
Examples
copal-morse cq cq de n0callsend it, at 13 words per minute
copal-morse -w 20 -f 700 sosfaster, and higher
copal-morse -q hello worldprint the dots and dashes only
copal-morse -pthe table
copal-morse -dthe drill (Ctrl-C to stop)
copal-morse -w 5 -da beginner's drill
Options
-w WPM- speed in words per minute (default 13)
-f HZ- tone in hertz (default 600)
-q- print the code, play nothing
-p- print the table and exit
-d- drill: it sends, you type
-h, --help- the usage
Notes
- In the drill, Enter alone repeats the group and
? shows it; it keeps score of right and wrong. - Speed is by the standard word PARIS: at W words per minute a dot lasts 1200/W milliseconds. Letters, digits and common punctuation are sent; anything else is skipped.
- It needs sox for sound (
doas apk add sox); without it, it prints the code instead.
See also sox, play, direwolf
copal-notify Put one sentence on this machine's screen: as a notification, a Hyprland banner, or on the console.
Copal · Copal's own · stage 16 · Join the named fleet, and announce it
On Copal: The fleet's "message" verb lands here -- the museum's "please stand back". It uses whatever the machine has, in order of how much screen it takes: a Hyprland overlay, a notification, or the whole console on a machine with no desktop.
Use
Give it the text as one argument. Mostly it is called by the fleet, but it works as a quick message to the screen from a script or over SSH.
Examples
copal-notify "Back in five minutes"
copal-notify "Build finished"from the end of a long script
Options
TEXT- the sentence to show (required; quote it)
Notes
- Inside Hyprland it uses
hyprctl notify for 8 seconds; otherwise notify-send as a critical notification; with neither it writes the text to /run/copal/banner and to tty1. - It takes the text as a single argument and never re-splits or interprets it. The fleet limits a message to 200 characters of letters, digits and
. , ! ? : - before it gets here.
See also copal-fleet-exec, notify-send, hyprctl
copal-readme-man Make a man page from a project's README.md, so man PROGRAM answers for programs built from source.
Copal · Copal's own · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts
On Copal: The programs in ~/code have READMEs and no man pages. This turns the parts of a README that are about using the program into a proper man page -- leaving out the badges, the build instructions and the licence -- so the manual works for them like everything else.
Use
copal-build runs it for every checkout it builds. Run it yourself to make or preview a page: give the README and the program names, and it writes roff to standard output.
Examples
copal-readme-man ~/code/staticstream/README.md sstr,ytq > sstr.1
copal-readme-man ~/code/ascitty/README.md ascitty > /tmp/a.1; man -l /tmp/a.1
copal-readme-man --markdown README.md ascittywhat goes in, as Markdown
Options
README NAME[,NAME...]- the page, as roff, on stdout
--markdown README NAME- the filtered Markdown instead, to review
Notes
- It keeps the sections about using the program and drops the title, badges, images and HTML, and the sections a user of the installed program does not need: building, installing, downloading, licence, contributing, credits, status, roadmap, changelog and internals.
- The NAME line lists every program named; the description is the first sentence of the README's first paragraph of prose. The date is the README's last commit, so the same README makes the same page.
- A README's
## becomes a section, its ### a subsection. lowdown does the conversion (doas apk add lowdown).
See also copal-build, lowdown, man
copal-remote Share this machine's screen on the local network for a limited time: VNC on X11, RDP on Wayland.
Copal · Copal's own · stage 16 · Join the named fleet, and announce it
On Copal: For looking at a fleet machine's screen from the console. The machine decides how -- the server that matches its desktop -- and the limits are set on the machine, not by whoever asks: its LAN address only, a deadline, a switch to forbid it, and a log line at each end.
Use
start shares the screen until the deadline (30 minutes unless set otherwise), stop ends it now, status says what is running. Starting again while it runs restarts the clock.
Examples
copal-remote statusis the screen shared?
doas copal-remote startshare it
doas copal-remote stopstop now
Options
start- share the screen on the LAN address, until the deadline
stop- stop sharing
status- session, server, mode, minutes and address (the default)
Notes
- On X11 it runs x11vnc on port 5900; on Wayland, hypr-rdp on 3389 with the node's certificate. Neither is part of a normal install.
- VNC asks for the fleet's screen password:
COPAL_FLEET_REMOTE_PASSWORD, set by make answers and kept on the node in /etc/copal/remote/passwd (root only). The console's seat answers with the same one. With no password set, stage 16 turns sharing off altogether, and start says why. - Classic VNC encrypts the login but not the screen, so keep it to a network you trust.
/etc/copal/remote/mode set to off forbids it -- the setting for a machine in a public place. /etc/copal/remote/minutes sets the deadline; 0 means none.- Wired interfaces are tried before wireless. Starts and stops go to
/var/log/copal-fleet.log.
See also copal-fleet-exec, x11vnc, hyprctl
copal-session Start this machine's desktop -- Hyprland or X11, whichever /etc/copal/session names.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: One front door for the graphical session. The console login, the autologin and the documentation all say "run copal-session", and a single word in /etc/copal/session decides what that means, so they can never disagree.
Use
Log in on a console as your own user and run it. With the word wayland (and Hyprland installed) it starts Hyprland; otherwise it runs startx.
Examples
copal-sessionthe desktop
cat /etc/copal/sessionwhich one it will start
doas copal-desktop x11change it, safely
Options
Notes
- It refuses to run as root: the desktop belongs to the admin user.
- For Wayland it makes
XDG_RUNTIME_DIR if nothing has (a private /tmp/xdg-runtime-UID, mode 700, refusing one someone else owns), then runs Hyprland through start-hyprland when present, inside dbus-run-session so the session's programs share one bus. - On the X path, if X's setuid helper has been disarmed it stops and names the fix,
doas copal-desktop x11, instead of letting startx fail with "Only console users are allowed to run the X server".
See also copal-desktop, copal-startx, copal-autologin
copal-shot Super+Shift+S: drag a rectangle, and that part of the screen is saved as a picture.
Copal · Copal's own · stage 17 · Hyprland and the Antiquity theme
On Copal: The Hyprland desktop's screenshot key. The theme binds hyprshot, which Alpine does not package; copal-shot does the same with grim (grab) and slurp (select), which it does.
Use
Press Super+Shift+S, then drag over the area you want; release and it is saved to ~/Pictures as screenshot-DATE-TIME.png (to /tmp if there is no Pictures folder). Escape cancels.
Examples
copal-shotselect a region, save it
grim ~/Pictures/whole.pngthe whole screen, with grim directly
grim -g "$(slurp)" - | wl-copya region straight to the clipboard
Options
Notes
- It saves without saying so: look in
~/Pictures. - For the whole screen, a window, or a copy on the clipboard, use grim directly, as in the examples.
- On the i3 desktop (X11) screenshots are
scrot; copal-shot is for Wayland.
See also grim, scrot, tesseract
copal-splash Draw the i3 desktop's key bindings onto the wallpaper, so the first screen teaches the keys.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: On the X11 desktop there is no welcome screen, and a tiling window manager with no visible menu is a blank wall to a newcomer. The keys, printed where the wallpaper would be, are the way in.
Use
i3 runs it at startup. Run it yourself after editing ~/.config/i3/keys.txt to see the change without logging out.
Examples
copal-splashredraw the desktop now
rm ~/.cache/copal-splash.png; copal-splashforce a fresh image
Options
Notes
- It draws the bindings and group headings from
keys.txt (the section from START SOMETHING to IF SOMETHING), at the screen's size from xrandr, with a line of the essential keys along the bottom. - The image is
~/.cache/copal-splash.png and is remade only when keys.txt is newer, so logging in costs nothing. - It needs ImageMagick to draw and feh to show; without them the desktop is a plain colour, set with xsetroot. It is for the i3 desktop only; Hyprland has its own wallpaper and Super+/ for the keys.
See also i3, copal-guide, feh
copal-ssh Read and change this machine's SSH login policy: passwords, root, and who may log in.
Copal · Copal's own · stage 6 · Install the SSH key from the card
On Copal: Copal writes its SSH policy as one marked block in sshd_config. This edits only that block, tests the result with sshd -t before reloading, and puts the old file back if sshd rejects it -- so a typo cannot lock you out of a machine you can only reach by SSH.
Use
copal-ssh shows the policy. The other forms need doas; each changes one setting and reloads sshd.
Examples
doas copal-sshwhat is in force
doas copal-ssh password offkeys only (refused if you have no key)
doas copal-ssh password onallow passwords again
doas copal-ssh root offno root login over SSH
doas copal-ssh users paul annaonly these accounts may log in
Options
status- password login, root login, allowed users, public keys
password on|off- allow or refuse password (and keyboard-interactive) login
root on|off- root by key only (prohibit-password), or refused
users NAME...- replace the AllowUsers list
Notes
password off refuses to act if the admin user has no ~/.ssh/authorized_keys, because it would lock the machine off the network. Copy a key in first (ssh-copy-id from your computer).- The block runs from
# >>> copal ssh policy >>> to # <<< copal ssh policy <<<; delete it by hand and OpenSSH's own defaults apply. Every change leaves the previous file as sshd_config.copal.bak. - Every form, even
status, needs root: sshd_config is not readable otherwise.
See also sshd, ssh-keygen, ssh-copy-id
copal-startx Start the X11 desktop as it should be started: not as root, with the right groups, and with a log kept.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: When X fails to start, the reason scrolls off the console it just took over. copal-startx is startx with that fixed: it refuses root, warns about missing groups, and writes every session's output to a file, printing the tail when the desktop exits with an error.
Use
Run it from a console login instead of startx; arguments are passed on to startx. On the Wayland desktop you want copal-session instead, which picks the right path for this machine.
Examples
copal-startxthe X11 desktop, logged
copal-logs xread the last session's log afterwards
COPAL_DEBUG=1 copal-startxone run with the debug collection
Options
(none)- start X, passing any arguments on to startx
Notes
- It refuses to run as root, and says which account to log in as. Plain
startx still works for the day you need a root desktop on purpose. - It warns if you are not in the
video, input and tty groups, with the doas adduser line that fixes it. - The log is
~/.local/state/copal/xsession-DATE.log, with xsession-latest.log linked to the newest. Two are kept; with debug on (doas copal-debug on) ten are kept, and Xorg's own log is copied into each. - The log header records the tty, groups and graphics devices -- the facts that decide whether X may start and that are gone afterwards.
See also copal-session, copal-logs, copal-debug, startx
copal-store Copal Apps from the command line: find programs by what they do, install and remove them, with everything they need.
Copal · Copal's own · stage 18 · The Copal Store, and OpenShot compiled
On Copal: The engine behind Copal Apps and the menu's Install: every program Copal offers is a playbook, and copal-store runs it -- from an Alpine package, a Flatpak, a build from GitHub source, or a clone into ~/code -- then adds its man page, its optionals (plugins, codecs, format loaders) and the groups it needs.
Use
list and info to look; install and remove to change things (they ask for doas). With no arguments it opens the store window, or terminal menus where there is no desktop.
Examples
copal-store list Gamesa shelf: status, id, name
copal-store info gimpwhat it is, where from, how it installs
doas copal-store install gimp ffmpeg # install, with man pages, optionals, access
doas copal-store remove gimpand remove
copal-store optionalsthe optionals table
doas copal-store optionals --installedcatch up everything already installed
doas copal-store accessthe groups installed programs need
copal-store summarywhat each build did: result, size, "with", "absent"
Options
list [SECTION]- every program, or one shelf
info ID- one program: description, source, install method
install ID...- install (with man pages, optionals and access)
remove ID...- remove
recipes- the programs built from source
optionals [PKG...|--installed]- the plugins and helpers; install them
access [USER]- the groups programs need: plugdev, wireshark, dialout...
manpages PKG...- the man pages of these packages
summary- the build record
log ID- one build's full log
Notes
- A build from source records what it compiled in ("with") and what it could not find ("absent") in the summary: the answer to which formats and codecs a build has.
- Its logs are in
/var/log/copal-store; the event stream Copal Apps reads is /var/log/copal/events. - Installed on medium and full installs (stage 18).
See also copal-apps, copal-install, apk
copal-terminal-theme Write a colour theme into the terminal emulators' configs: foot, kitty, alacritty and the rest.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: The terminal part of the desktop's look, on its own: copal-theme calls it, and it can be run by hand for a different terminal palette or opacity.
Use
Name a theme and it writes it into every terminal configuration in your home; with no name it follows the desktop's current theme. Open terminals pick it up when they next start.
Examples
copal-terminal-themefollow the desktop's theme
copal-terminal-theme --listthe palettes there are
copal-terminal-theme sandCopal's own light palette
copal-terminal-theme night --alpha 1 # Tokyo Night, fully opaque
copal-terminal-theme --show erisprint a palette, change nothing
Options
THEME- helios, eris, priapus, eros, hades (Linux Antiquity), night, sand
--list- the theme names --show THEME print the palette and stop
--alpha A- window opacity, 0.5 to 1 (default 0.9)
Notes
$COPAL_TERMINAL_THEME overrides what "follow the desktop" means.- Only terminals already configured in your home are rewritten; a terminal installed later gets the theme the next time this runs.
See also copal-theme, foot
copal-theme One switch for the whole desktop's look: bar, borders, wallpaper, GTK, terminal, menus and editor together.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: Copal's desktop is themed in a dozen places -- Hyprland, the bar, wofi, GTK, the terminal, Neovim, mc. copal-theme changes all of them at once, so nothing is left in the old colours.
Use
With no argument it lists the themes, the current one starred. A name switches to it; --toggle swaps light and dark; --pick offers a menu (Super+Shift+T, or Style in the menu).
Examples
copal-themethe themes, * the current
copal-theme tokyo-nightswitch everything to it
copal-theme --togglelight <-> dark (Super+Shift+N)
copal-theme --pickchoose from a menu
copal-theme --show antiquitya theme's colour tokens
Options
NAME- switch to NAME
--toggle- the current theme's light or dark partner
--pick- choose from a menu (Super+Shift+T)
--show [NAME]- print a theme's tokens
-q, --quiet- say nothing but errors
Notes
- The colours are written to
~/.config/copal/current/colors.css, which the bar, wofi and the Super+A menu read: a running Neovim follows the change without restarting. - Themes shipped: Antiquity (helios, light) and Tokyo Night (dark).
See also copal-terminal-theme, copal-wallpaper, copal-gui
copal-times How long each package took to install, which ones pulled in the most, and what could be reordered.
Copal · Copal's own · written on every run of the installer
On Copal: A Copal install is hours on a small board, and the time goes somewhere measurable. The installer records every package's time and dependencies; this reads that record to show what was slow and, more usefully, which package's position in the order decided what everything after it cost.
Use
With no argument: the fifteen slowest packages and the total. groups shows the time by stage section; order and shared are the views for deciding what to install first.
Examples
copal-timesthe slowest fifteen
copal-times groupstime by section
copal-times orderwhat pulled the most in, and where it sat
copal-times sharedprerequisites many packages needed
copal-times deps gccwhat gcc brought with it
copal-times totalone line: packages, failures, time
copal-times csv > times.csvfor a spreadsheet
Options
(none), top- the slowest fifteen, and the summary
all- every package, slowest first
groups- time and count by section
order- the packages that pulled in the most, with their position
shared- dependencies wanted by more than one package
deps PKG- what one package brought with it
total- packages, already present, failed, and the install time
csv- the whole record as CSV
--motd- rewrite the login message's summary (needs doas)
--reset- clear the record (needs doas)
-h, --help- the usage
Notes
- PULLED is how many other packages came with one. A long time with "-" is a package that is genuinely expensive; a long time with "+13" is one that happened to be asked for first and paid for the dependencies.
- The record is
/var/lib/copal/install-times.tsv, with dependency sets in install-deps.tsv; older six-column records still read.
See also apk, copal-install
copal-wallpaper Choose and paint the desktop's wallpaper, from the theme's collection or your own pictures.
Copal · Copal's own · stage 17 · Hyprland and the Antiquity theme
On Copal: Hyprland's own wallpaper tool, hyprpaper, is not packaged for Alpine; copal-wallpaper paints with swaybg, remembers the choice, and is what the session starts.
Use
--pick shows thumbnails to choose from; set FILE uses any picture. Without arguments it paints the chosen one and keeps running -- the session starts it that way.
Examples
copal-wallpaper --pickchoose, with thumbnails
copal-wallpaper set ~/Pictures/lake.jpgany picture of yours
copal-wallpaper --listwhat is available, and from where
copal-wallpaper --fetchdownload diinki's published collection
Options
--pick- choose one, with thumbnails
set FILE- use FILE from now on
--list- the wallpapers, and where each came from
--fetch- download the theme author's full collection
Notes
- The bundled wallpapers are in
~/.config/hypr/wallpapers_bundled; --fetch adds the rest of the collection. - The choice is remembered across logins;
set is all it takes.
See also copal-theme
copal-widgets The clock, date and weather on the wallpaper: show them, hide them, and see where they come from.
Copal · Copal's own · stage 4 · X.Org, i3, a terminal and a browser
On Copal: The desktop layer's widgets. The theme's own widget shell, quickshell, is not packaged for Alpine, so waybar draws them; this command turns them on and off without touching the bar, and seeds the theme's own widget file for the day quickshell arrives.
Use
--off hides them, --on brings them back, both at once; --status says which are running and from where.
Examples
copal-widgets --statuswhat is running
copal-widgets --offhide the clock and weather now
copal-widgets --onshow them again
copal-guide widgetsthe longer version
Options
--on- show the widgets
--off- hide them
--status- which are running, and from where
--seed- place the theme's widgets in its quickshell file (run at login)
Notes
- What is drawn and where is
~/.config/waybar/desktop.json; the type and colours, desktop.css beside it. Nothing regenerates those files once they exist, so edits stay.
See also copal-bar, copal-theme
Code
ascitty A raytraced city of typeable characters, in real time in a terminal -- with a taxi game inside.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man ascitty(1), from its README
On Copal: One of the checkouts in ~/code, built by copal-build: a showpiece for a colour terminal, and a test of one. The same city runs on a Commodore Plus/4.
Use
Start it and a cab drives itself round the city, taking fares. Touch a key and you are driving: wasd is the vehicle, the arrows are the view, and \ hands it back to the autopilot. The frame is the size of the window, so a bigger terminal is a bigger city.
Examples
ascittythe city, the cab driving itself
ascitty --playat the wheel from the start
ascitty --walkon foot instead
ascitty --copterabove the city
ascitty --mode ascii --color none7-bit, no colour: the mode the name is about
ascitty --shot 30 > city.txtrender 30 frames, keep the last as text
ascitty --bench200 frames as fast as it can, and a report
w a s d (in the city) throttle, steer left, brake/reverse, steer right
q e hard left / hard right
space z brake / handbrake
t get out and walk
\ back to the autopilot; Esc quit
Options
--play- drive from the start, no autopilot
--walk- on foot
--copter- in the air
--mode M- ascii or unicode (default unicode)
--color D- true, 16 or none (default: from $COLORTERM)
--size WxH- a fixed frame instead of the window's size
--fps N- frame rate cap (default 30)
--seed N- another city
--sky N- start at phase N of 12: 0 night, 3 sunrise, 5 noon, 8 sunset
--shot [N]- render N frames, print the last, exit
--bench- measure the renderer
Notes
- The terminal is the bottleneck, not the renderer: a big frame takes the renderer a millisecond and the terminal twenty. Bands of the picture a frame behind mean the terminal is falling behind -- a smaller window or
--fps 15 fixes it. - Hold the keys: the throttle winds on while it is down, as the steering does, so a tap does very little.
--color follows $COLORTERM; set --color 16 if the colours look wrong over SSH.
See also copal-build, copal-terminal-theme
birdshot Bird and sky capture for the Raspberry Pi HQ Camera, from the command line.
Code · command-line tool · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man birdshot(1), from its README
On Copal: Copal's camera. copal-build builds the C++ pipeline from the birdshot checkout; birdshot-gui is its window (Super+Shift+B), and this is the same pipeline for a script or an SSH session.
Use
Capture with metered auto-exposure and quality gates that drop blurred or badly exposed frames, fast bursts, timelapses, or a watch on the sky that fires when a bird crosses it. Then stamp the EXIF and assemble a session's frames into a video.
Examples
birdshot infothe camera, its modes, storage, calibration
birdshot doctorwhat is missing or wrong, and the fix
birdshot capture -n 200200 frames through the full pipeline
birdshot rapid -n 500the fastest path: flat, timed names
birdshot timelapse -i 5 -n 720one frame every 5 s, for an hour
birdshot birdflight -n 20watch the sky; fire on a bird, 20 takes
birdshot sessionswhat has been captured, by session
birdshot assemble SESSION --fps 60a session's frames into an MP4 (ffmpeg)
birdshot sunthe sun now, and today's events
Options
capture [-n N] [-v]- the full pipeline, with quality gates
rapid [-n N]- fastest single photos
timelapse [-i SEC] [-n N]- one frame every SEC seconds
birdflight [-n TAKES]- trigger on a bird
gui [--port N]- the live pipeline in a browser
exif DIR- stamp EXIF into a session, losslessly
assemble DIR [--fps N]- frames to a movie; --out FILE
sun / plan / site- where the sun is, a plan for the days ahead, your site
info / sessions / doctor / selftest- the housekeeping
--config PATH- another settings file
Notes
- It is for an IMX477 -- the Pi HQ Camera. Other cameras are not what its exposure ladder and gates are tuned for;
birdshot doctor says what it found. - Settings live in
~/.config/birdshot/settings.json; every command reads it, and --config points at another. - The first run of the window offers a calibration wizard, about a minute. Its numbers are what the quality gates judge by: run it.
See also copal-camera, copal-build
copal-tm Copal's task manager: an instrument panel and a process browser in one terminal window.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man copal-tm(1), from its README
On Copal: The task manager on Copal's full install, built by copal-build from its checkout: what the machine is doing, which process is doing it, and a considered way to stop one.
Use
The top half is the instrument panel -- CPU, memory, swap, temperature, network, pressure; the bottom half is the process tree. Select a process and press k to send it one signal, or x for the Halt plan: the gentle signals first, the hard one last, with the reasons shown.
Examples
copal-tmthe panel and the browser, split
copal-tm --view dashboardthe instrument panel only
copal-tm --view browserthe process list only
copal-tm --refresh 0.5tick twice a second
copal-tm --dump-config > ~/.config/copal/taskman.confa config to edit
F1 F2 F3 (in the window) dashboard / split / browser
Enter i the Inspector: attributes, contents, network, tools, access
k x send one signal / the Halt plan
/ s t filter / sort / tree
T the Transcript: every signal sent, and why
? q keys / quit
Options
--view MODE- split, dashboard or browser
--refresh SECONDS- the tick, 0.25 to 10 (default 1.0)
--charset SET- auto, full, blocks or ascii
--color MODE- auto, truecolor or 16 --browser.sort KEY cpu, mem, pid, time, name or user
--theme NAME- copal or mono
--simulate- run against a simulated machine
--dump-config- print the effective configuration
Notes
k shows each signal's disposition -- whether the process catches, ignores or dies of it -- before you send it; the Halt plan uses those.- The configuration is
~/.config/copal/taskman.conf, key = value, and every key is also a flag of the same name. - It degrades legibly: on a 16-colour console or an ASCII-only terminal it still draws, with
--charset ascii.
See also htop, btop, copal-halt
orrery The console for a fleet of Copal machines: the wall, the seat, and the museum interface.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man orrery(1), from its README
On Copal: Stage 16's fleet -- a room of Copal machines -- is watched and run from it: every machine at once on the wall, one of them full screen in the seat. Built by copal-build from the orrery checkout.
Use
Three faces. The wall is a web page of every machine in the fleet, served on a port. The seat is one machine, observed and controlled over VNC, full screen in this terminal. The native window (--gui) is the museum interface. Without --operator it only observes; with it, the verbs that act on machines are enabled.
Examples
orrery --demothe wall, from a fixture: no fleet needed
orrery --gui --demo --operator xthe museum interface, from the fixture
orrerythe wall, on 127.0.0.1:8080
orrery --listen 0.0.0.0:8080the wall, for the room's gallery screen
orrery --gui --operator TOKENthe window, with the write verbs on
orrery --seat museum-01one node, full screen, over VNC
Options
--listen HOST:PORT- where the wall is served (default 127.0.0.1:8080)
--operator TOKEN- enable the verbs that change machines
--fleet NAME- which fleet (passed to copal fleet)
--demo- serve from a fixture instead of a fleet
--gui- the native window instead of a web page
--seat NODE- one node over VNC; --fps N, --vnc-port N
--frame PATH- render one frame to a PPM and exit (works headless)
--dark- the night palette
--quiet- do not log requests
Notes
- The default listens on loopback only. The gallery screen needs
--listen 0.0.0.0:8080, which puts the wall on the LAN: a LAN you trust. - Read-mostly by default is deliberate.
--operator is what turns a display into a control panel. - The seat asks a node for 6 frames a second, because frame rate is the expensive axis;
--fps raises it.
See also copal-fleet, ssh
radbeeper A GQ GMC Geiger counter on the desk: find it, watch it, log it, and pull its history.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man radbeeper(1), from its README
On Copal: Stage 10 sets up the Geiger counter; radbeeper, built by copal-build from its checkout, is the command the counter's instrument panel (radbeeper-gui) is built on.
Use
Plug the counter in by USB, radbeeper probe to find it, radbeeper watch to see its rate over five time spans at once while it logs. It also downloads what the counter recorded on its own, and turns the timing of decays into random numbers.
Examples
radbeeper probefind the counter, say what it is
radbeeper watchthe monitor, logging while it is open
radbeeper cpmits counts per minute, once
radbeeper clockits clock against this machine's
radbeeper clock --setcorrect it
radbeeper log pulldownload the history in its flash
radbeeper backfillfill the log's gaps from that history
radbeeper random256 bits of hex, from decay timing
Options
probe- find and identify the counter
watch- the live monitor
cpm- one reading
clock [--set]- compare, or set, the counter's clock
log info|pull- what history it holds / download it
backfill- fill gaps in the log from the counter's memory
random- random bits from decay timing; --check F to verify a log
-d, --device PATH- the serial port; repeat for a second counter
-b, --baud RATE- the baud (default: 115200, then 57600)
--duration SECONDS- stop after this long
--logs DIR- where logs are written and read
Notes
- Nothing found?
probe says what went wrong, because each cause has its own fix. "Permission denied" means the account is not in dialout, which owns the serial port: doas adduser $USER dialout, then log in again. - Set the clock first (
clock --set): the history in the counter's flash carries the counter's own timestamps. - The default tube factor is 151.5 CPM per µSv/h, the GMC-320's;
--cpm-per-usvh for another tube. doas dmesg | tail after plugging it in shows the serial port it got.
See also copal-build, dmesg
sstr Record a stream into a .sstr file, with its order, pace and damage tolerance kept, and play it back.
Code · command-line tool · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man sstr(1), from its README
On Copal: The archive format ytq keeps its downloads in. Built by copal-build from the staticstream checkout; sstr export turns captures back into ordinary files whenever you want them.
Use
sstr record writes a stream -- a file, or stdin -- into a capture; sstr play lets it out again: to a file, to stdout at the pace it was recorded, or to VLC or mpv over the network. Every record carries Reed-Solomon parity (about 21 % more bytes), so a damaged capture is repaired as it is read. Nothing is encrypted and nothing is decoded.
Examples
sstr record talk.sstr --input talk.mp4capture a file
sstr play talk.sstr -o talk.mp4and back out as the file
sstr play talk.sstr --paced | mpv -at the pace it was recorded
sstr play talk.sstr --serve :8080serve it to a player on the LAN
sstr verify talk.sstrcheck it; say what was repaired
sstr export ~/Videos/archiveevery capture in a folder, back to files
sstr export . -nwhat that would write, first
sstr config listthe settings in force
Options
record OUT- capture stdin, or --input FILE, into OUT
play IN- write the stream back; -o FILE, --paced, --speed N
play IN --serve A- serve it over HTTP at HOST:PORT
verify IN- check every record and signature
export PATH...- captures or folders back to files; -r, -n, --into DIR
config- list, get, set or unset a setting
--key KEY- sign the checkpoints with this SSH key
--allowed-signers F- trust signatures by these keys, when reading
-- as IN or OUT: stdin or stdout
Notes
- Checkpoints are signed with your SSH key, which proves who recorded it; they are not encrypted. Anyone with the file can play it.
export with --remove deletes each capture once its file is out and checked; without it, both stay.- A capture can be played or served while it is still being recorded:
--follow keeps going as it grows, so mpv or VLC can watch it live.
See also ytq, sstr-workspace
sstr-workspace One terminal window over the download queue and the archive: browse, play, verify, export.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man sstr-workspace(1), from its README
On Copal: Super+Shift+A. The Workspace over ytq's queue and the folders of Static Stream captures it fills, from the staticstream checkout -- every action one key, and every action a command line you can read.
Use
A column browser. Move through folders and the queue, look at a capture in the Inspector, and send it a Service -- play, verify, export -- with one key. Each Service is written into the Transcript as a command line before it runs, so you see exactly what was done and can type it again.
Examples
sstr-workspacethe download queue, live
sstr-workspace ~/Videos/archivebrowse a folder of captures
up/down j/k (in the window) move
Enter l open a folder; h back out
Space put the selection on the Shelf, or take it off
p P s v play / play paced / serve / verify
x t a export / text / armor
r f retry / forget a queue entry
Q ytq's queue as one more column; q leave
Options
DIR- browse DIR instead of the queue
Space- the Shelf: a Service then goes to everything on it
d- one line per queue entry, or two
Notes
- The archive folder is
ARCHIVE_DIR in ~/.config/copal/media.conf, then ~/.config/ytq/config -- where ytq reads it. The player (mpv) and the serve address come from the same files. - A Service that prints takes the terminal until a key is pressed; the window comes back after it.
See also ytq, sstr
ytq A download queue that watches the clipboard, and keeps what it fetches as Static Stream.
Code · terminal program · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man ytq(1), from its README
On Copal: Copy a video's link, press Super+Shift+Y, and it is queued. Built by copal-build from the staticstream checkout in ~/code; the Rust ytq replaced the Python one Copal used to write.
Use
Queue links, then download them one at a time with yt-dlp, best video and audio merged. The queue is one file shared by every ytq at once, so ytq add works while ytq run is downloading. Each download also gets a .txt beside it: the full title, author, URL, dates, the description and the captions, so it can be cited later.
Examples
ytqthe queue window; queues the clipboard's URL
ytq clipqueue what is on the clipboard (Super+Shift+Y)
ytq add https://youtu.be/dQw4w9WgXcQ # queue a URL from the shell
ytq rundownload everything queued, here
ytq statuswhat is downloading, and what is left
ytq listevery entry: queued, done, waiting, failed
ytq transcript URLonly the captions, as text
ytq cookiesretry what waited for a Brave sign-in
touch ~/.config/ytq/autostart downloading by itself from now on
Options
clip- queue the clipboard's URL, or every YouTube link in it
add URL...- queue URLs
run- download the queue in this terminal
status / list- the current download / every entry
retry URL- put an entry back (r in the window)
forget URL- take one out; the downloaded file stays (d)
clear- forget finished and failed entries; files and log stay
cookies- retry the entries waiting on a sign-in (c)
--mp4- keep the video file, write no capture
--sstr- keep a Static Stream capture, remove the video once checked
--both- keep the two
--run / --no-run- start a runner this once / never
Notes
- Nothing downloads until something runs the queue:
ytq run, the window, or autostart (~/.config/ytq/auto). Without that file, clip and add only queue. - A login, age gate or "confirm you are not a bot" page opens Brave on the URL: sign in there, then
ytq cookies. A second failure is final. - What it keeps by default is a
.sstr capture, not a video file. sstr export DIR turns a folder of them back into ordinary files. - The log is
~/.local/share/ytq/ytq.log; the queue is ~/.local/share/ytq/queue.json.
See also sstr, sstr-workspace, copal-build
Development
gcc The GNU C and C++ compiler.
Development · gcc 15.2.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man gcc(1) · home
needs binutils, libgcc-static, libgomp, libatomic, gmp, isl25, mpc1, mpfr4
On Copal: Stage 7 installs build-base -- gcc, make and the musl headers -- because most things built on a Copal machine start here: the checkouts in ~/code, the store's source builds, your own programs.
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
Only the most useful options are listed here; see below for the remainder. g++ accepts
mostly the same options as gcc.
Use
Compile C (gcc) or C++ (g++) source into a program, or into object files for a larger build. Warnings on and debug information in is the right default while writing; optimisation for the version you keep.
Examples
gcc -Wall -Wextra -g hello.c -o hellocompile, warnings on, debuggable
./hellorun it
gcc -O2 -o hello hello.coptimised
g++ -std=c++20 -Wall main.cpp -o mainC++, a chosen standard
gcc -c util.cobject file only, for linking later
gcc main.o util.o -lm -o proglink, with the maths library
gcc -static hello.c -o helloone file, no shared libraries
cd ~/dev/hello && make runCopal's sample project
Options
-o FILE- name the output
-c- compile only, make a .o
-g- debug information, for gdb
-O2- optimise; -O0 for none, -Os for size
-Wall -Wextra- the warnings worth having
-std=c17- the language standard: c89 c99 c11 c17 c23, c++17 c++20 c++23
-I DIR- another directory of headers
-L DIR -lNAME- link libNAME from DIR
-static- link everything in
-E- preprocess only
Notes
- The C library is musl, not glibc. Code that uses glibc extensions (
execinfo.h's backtrace, some _GNU_SOURCE corners) will not find them. A binary built on Debian will not run here, nor the reverse. -fsanitize=address and -fsanitize=undefined fail to link: Alpine ships no sanitizer runtimes. Use valgrind for memory errors.-static is cheap and reliable on musl -- a static binary copies to another Copal machine of the same architecture and runs.- Missing header? The library's
-dev package has it: apk add openssl-dev for openssl/ssl.h.
See also clang, make, gdb, valgrind, cmake
git Version control: keep a project's history, branch it, and share it.
Development · git 2.54.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man git(1) · home
needs libcurl, libexpat, pcre2, zlib
On Copal: Stage 7 clones your repositories into ~/code with it, and sets its identity from the answers given on the Mac. copal-code pulls and rebuilds every checkout through it; Copal itself is a git checkout.
git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]
[--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]
[--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]
<command> [<args>]
Use
Record changes as commits, move between versions, and exchange them with a remote such as GitHub. The daily loop is short: status, add, commit, pull, push.
Examples
git statuswhat changed, what is staged
git add -pstage changes a piece at a time
git commit -m 'Fix the menu order'record them
git pull --rebasebring in others' work, yours on top
git pushsend your commits
git log --oneline --graph -20recent history as a tree
git diff HEAD~1what the last commit changed
git switch -c try-thisa new branch, and onto it
git restore file.cthrow away uncommitted edits to a file
Options
status- the working tree against the last commit
add -p- stage hunk by hunk, asking for each
commit -m MSG- commit with a message; --amend to redo the last one
pull --rebase- fetch, then replay your commits on top
log --oneline- one line per commit; --graph draws the branches
diff / diff --staged- unstaged / staged changes
switch -c NAME- create a branch and switch to it
restore FILE- discard working-tree changes; --staged to unstage
stash / stash pop- set changes aside, and bring them back
remote -v- where fetch and push go
Notes
- Stage 7 clones over SSH when it can and over HTTPS when it cannot. HTTPS checkouts pull but cannot push without a token: make a key (
ssh-keygen -t ed25519), add its .pub to GitHub, then git remote set-url origin git@github.com:you/thing.git. - The identity comes from stage 1's answers:
git config --global user.email shows it, and sets it. git restore and git reset --hard discard work with no undo. When unsure, git stash first: it keeps the changes where you can get them back.- With
delta installed (the catalogue's System section), git config --global core.pager delta makes diffs coloured and clearer.
See also ssh-keygen, ssh, make, copal-code, copal-build
make Rebuild what is out of date, by the rules in a Makefile.
Development · make 4.4.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man make(1) · home
On Copal: The build tool behind Neovim's F5 (:make) and stage 7's sample project in ~/dev/hello, and the front door of most checkouts -- Copal's own repository included (make lint, make commands).
make [OPTION]... [TARGET]...
Use
Run in a directory with a Makefile: make builds its first target, make NAME a named one. It compares file times, so only what changed is rebuilt.
Examples
makebuild the default target
make -j4four jobs at once (a Pi 4 has four cores)
make runa named target: build, then run
make cleanremove what was built
make -nprint the commands, run none
make -C ~/dev/hellorun it in another directory
make CC=clang CFLAGS='-O2 -g'override a variable for this run
Options
-j N- run N jobs in parallel
-n- dry run: show the commands
-C DIR- change to DIR first
-B- rebuild everything, dated or not
-k- keep going after an error
-s- silent: do not echo the commands
VAR=VALUE- set a variable, overriding the Makefile's
Notes
- Recipe lines start with a TAB, not spaces. "missing separator" means an editor put spaces there.
-j with more jobs than RAM can hold: on a 512 MB board, make -j1 and zram are safer than a build killed halfway.- In Neovim, F5 saves and runs
:make; the errors land in the quickfix list, and ]q and [q walk them.
See also gcc, cmake, ninja, nvim
ninja Run a build that cmake or meson generated, fast and in parallel.
Development · samurai 1.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ninja(1) · home
On Copal: The builder behind cmake -G Ninja and every meson project. On Alpine the command is samurai, a small compatible reimplementation (/usr/bin/samu); what it lacks, few builds use.
samu [-C dir] [-d debugflag] [-f buildfile] [-j maxjobs] [-k maxfail] [-w warnflag=action]
[-nv] [target...]
samu [-C dir] [-f buildfile] -t clean [-gr] [target...]
samu [-C dir] [-f buildfile] -t compdb [-x] [rule...]
samu [-C dir] [-f buildfile] -t commands [target...]
samu [-C dir] [-f buildfile] -t query [target...]
samu [-C dir] [-f buildfile] -t targets [depth [maxdepth]]
samu [-C dir] [-f buildfile] -t targets rule [rulename]
samu [-C dir] [-f buildfile] -t targets all
samu -t list
Use
Run it in (or point it at) a build directory that has a build.ninja. You rarely write that file yourself: cmake or meson writes it, and ninja builds from it, running as many jobs as there are cores.
Examples
ninja -C buildbuild in ./build
ninja -C build -j2two jobs (a small board's RAM)
ninja -C build -vshow every command
ninja -C build -t cleanremove what it built
ninja -C build -t targetswhat can be built
ninja -C build -t compdb > compile_commands.jsonfor clangd
Options
-C DIR- change to DIR first
-j N- N jobs at once (default: cores + 2)
-k N- keep going until N failures
-n- dry run
-v- print each full command
-t TOOL- a subtool: clean, targets, commands, compdb, query
Notes
- It is samurai:
-t graph and a few other ninja subtools are not there ("unknown tool"). Builds themselves behave the same. - The default job count assumes enough memory for each. On a 512 MB Pi, a C++ build at
-j3 swaps hard; pass -j1 or -j2. - Do not edit
build.ninja: the next cmake or meson run rewrites it.
See also cmake, make, meson
nvim Neovim: a modal text editor, set up by Copal as a small IDE.
Development · neovim 0.12.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man nvim(1) · home
needs lua5.1-lpeg, tree-sitter-c, tree-sitter-lua, tree-sitter-markdown, tree-sitter-vim, tree-sitter-vimdoc, tree-sitter-query, libintl
On Copal: Stage 7's editor. Copal's configuration gives it building (F5), the error list, a debugger (F4), language servers and LazyVim-shaped keys -- with no plugin manager and nothing to download.
nvim [options] [file ...]
nvim [options] -
nvim [options] -t tag
nvim [options] -q [errorfile]
Use
Open a file, edit in insert mode, move and change text in normal mode. On a Copal machine it also builds and debugs: F5 runs make, the errors land in a list, and the language server answers "where is this defined" and "who calls this". Space is the leader key: press it and wait for the menu of what follows.
Examples
nvim main.copen a file
nvim +42 main.cat line 42
nvim -d old.c new.cside-by-side diff
copal-guide nvimCopal's tutorial, from nothing to useful
F5 (in nvim) save and build; ]q / [q walk the errors
gd gr K go to definition / references / documentation
Space ci who calls this function
F9 F4 breakpoint here / start the debugger
Ctrl-O back to where you jumped from
:Lsp which language servers this machine has
Options
+N- open at line N
-d A B- diff mode
-R- read-only
--clean- start with no configuration at all (to test a problem)
:w- :q :wq (in nvim) write, quit, both; :q! quits without saving
i- Esc (in nvim) into insert mode, back to normal mode
u- Ctrl-R (in nvim) undo, redo
Notes
- The configuration is layered, and one part is yours:
~/.config/nvim/local.lua is never written by Copal and runs last. init.vim, theme.lua, keys.lua and lsp.lua are rewritten when stage 7 runs again. - Language servers need the project's build flags for C and C++: a
compile_commands.json, from bear -- make or cmake. - The colours follow the desktop's theme, even in a running editor.
:Tutor inside nvim is the half-hour lesson in the modal part.
See also make, gdb, git, tmux, clang
pip Install Python packages from PyPI -- inside a virtual environment.
Development · py3-pip 26.1.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man pip(1) · home
needs python3
On Copal: Stage 7 installs it for the packages Alpine does not carry. On Alpine it refuses to touch the system's Python, and that refusal is the most-asked question about it.
pip <command> [options]
Use
Make a virtual environment for the project, enter it, and pip installs there -- not into the system. For a command-line tool you want everywhere, pipx does the same for one program at a time.
Examples
apk search -e py3-requestsfirst: does apk have it?
python3 -m venv .venv && . .venv/bin/activatea venv, entered
pip install requestsinto the venv
pip install -r requirements.txta project's list
pip freeze > requirements.txtwrite that list
pip list --outdatedwhat could be upgraded
doas apk add pipx && pipx install yt-dlpa tool, in its own venv, on PATH
Options
install PKG- install; -U to upgrade; ==VER for a version
install -r FILE- install every line of FILE
uninstall PKG- remove
list- what is installed; --outdated
show PKG- version, location, dependencies
freeze- installed packages as a requirements file
Notes
- "error: externally-managed-environment" outside a venv is Alpine protecting apk's Python.
--break-system-packages overrides it and means what it says: a later apk upgrade can break both. - A package with C inside may have no musl wheel and compile instead, which needs
build-base python3-dev and, on a Pi, patience. pip install --user is refused too. pipx is the tool for per-user programs; it puts them in ~/.local/bin, which Copal puts on PATH.
See also python3, apk
Devtools
bear Record a build's compiler calls into compile_commands.json, for clangd and other tools.
Devtools · command-line tool · bear 4.1.5 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man bear(1) · home
On Copal: The catalogue's bridge between a Makefile and the editor: clangd needs each file's flags, and a plain make build does not write them down. Bear watches the build and does.
bear [OPTIONS] [--] [BUILD_COMMAND...]
bear intercept [OPTIONS] [--] BUILD_COMMAND...
bear semantic [OPTIONS]
Use
Put bear -- in front of the build command. Afterwards compile_commands.json sits in the current folder, and clangd -- in Neovim, Helix or Geany -- understands the project.
Examples
bear -- makerecord a make build
make clean && bear -- make -j4a full rebuild, so every file is seen
bear --append -- make extraadd to an existing file
bear --output build/cc.json -- makewrite it somewhere else
Options
--- everything after is the build command
--output FILE- where to write (default compile_commands.json)
--append- add to the file instead of replacing it
Notes
- Only files that are compiled during the run are recorded: after a
make that had nothing to do, the file is empty. Clean first. - CMake and Meson write the same file themselves; Bear is for builds that do not.
See also clangd, make, cmake
ccache A compiler cache: a rebuild of unchanged code takes seconds instead of minutes.
Devtools · command-line tool · ccache 4.13.6 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ccache(1) · home
needs hiredis, libxxhash, zstd-libs
On Copal: The catalogue's rebuild accelerator -- worth most on a Pi, where compiling is slow and the same sources are often built again after a make clean or a branch switch.
ccache [ccache options]
ccache [KEY=VALUE ...] compiler [compiler options]
compiler [compiler options]
The first form takes options described in COMMAND LINE OPTIONS below. The second form invokes
the compiler, optionally using configuration options as KEY=VALUE arguments. In the third
form, ccache is masquerading as the compiler as described in RUN MODES.
Use
Put it in front of the compiler. It remembers each compilation's result by its inputs; the same file with the same flags later comes from the cache. It is not switched on by default.
Examples
CC="ccache gcc" makeone build, through the cache
export PATH=/usr/lib/ccache/bin:$PATHevery gcc/cc call, from now on
cmake -B build -DCMAKE_C_COMPILER_LAUNCHER=ccachefor a CMake project
ccache -shits, misses and cache size
ccache -Cempty the cache
Options
-s, --show-stats- statistics: hits, misses, size
-z, --zero-stats- reset the statistics
-C, --clear- empty the cache
-M, --max-size SIZE- set the cache limit, e.g. 5G
-p, --show-config- the settings in force
Notes
- The cache is
~/.cache/ccache, 5 GB at most by default; on a small card, ccache -M 1G. /usr/lib/ccache/bin holds links named gcc, cc, g++ and the rest, which is what makes the PATH method cover everything.
See also gcc, clang, make, cmake
cgdb gdb with a source window above it, in the terminal: see the code as you step.
Devtools · terminal program · cgdb 0.8.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs gdb, libncursesw, readline
On Copal: The catalogue's lightweight debugging front end: gdb's commands, with the current line shown in the source -- the simplest way to see where a program is, over SSH or on a console.
Use
Start it as you would gdb. The top half shows the source with the current line marked; the bottom half is gdb itself. Escape moves to the source window, i back to gdb.
Examples
cgdb ./progdebug a program
cgdb -- --args ./prog -v in.txtgdb options after --
cgdb -d gdb-multiarch ./arm-binarywith another gdb
Esc (in cgdb) to the source window: vi keys to move, / to search
Space (source window) set or clear a breakpoint on this line
i back to the gdb window
break / run / next / step / print (gdb window) as in gdb
Options
-d DEBUGGER- the gdb to run
--- the rest goes to gdb
Notes
- Build with
-g: without debug information there is no source to show. - Its settings go in
~/.config/cgdb/cgdbrc (for example set syntax=on, or a colour scheme).
See also gdb, lldb, pwndbg
cl65 Compiler Suite for 6502 based processors
Devtools · command-line tool · cc65 2.19 · stage 12 · The application catalogue · home
No notes yet: the facts above are read from apk and the man page.
cmake Generate a project's build files -- for ninja or make -- from its CMakeLists.txt.
Devtools · command-line tool · cmake 4.2.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man cmake(1) · home
needs libarchive, libcrypto3, libexpat, rhash-libs, libssl3, libuv, zlib
On Copal: Stage 7 installs it because a large share of C and C++ projects build only through it; several of the store's source builds do.
Generate a Project Buildsystem
cmake [<options>] -B <path-to-build> [-S <path-to-source>]
cmake [<options>] <path-to-source | path-to-existing-build>
Build a Project
cmake --build <dir> [<options>] [-- <build-tool-options>]
Install a Project
cmake --install <dir> [<options>]
Open a Project
cmake --open <dir>
Run a Script
...
Use
Two steps, always in a separate build directory: configure (read CMakeLists.txt, find the compiler and libraries, write the build files), then build. Configure once; after that, only the build step.
Examples
cmake -B build -G Ninjaconfigure into ./build, for ninja
cmake --build buildbuild (runs ninja or make for you)
cmake --build build -j4with four jobs
cmake -B build -DCMAKE_BUILD_TYPE=Releaseoptimised
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ONfor clangd in nvim
doas cmake --install buildinstall to /usr/local
cmake -B build --freshreconfigure from nothing
Options
-B DIR- the build directory (made if missing)
-S DIR- the source directory (default: here)
-G NAME- the generator: Ninja, or "Unix Makefiles"
-D VAR=VALUE- set a cache variable: CMAKE_BUILD_TYPE, CMAKE_INSTALL_PREFIX...
--build DIR- build a configured tree
--install DIR- install it
--fresh- forget the cached configuration
-j N- with --build: parallel jobs
Notes
- The cache remembers. A changed compiler or a library installed after the first configure is not noticed until
--fresh or rm -rf build. - "Could NOT find Foo": install the library's
-dev package (apk search -e foo-dev), then configure again with --fresh. CMAKE_BUILD_TYPE is empty by default: no optimisation and no debug information. Say Debug or Release.
See also ninja, make, gcc, clang
cppcheck Static analysis for C and C++: find bugs the compiler does not warn about.
Devtools · command-line tool · cppcheck 2.21.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man cppcheck(1) · home
needs pcre, tinyxml2
On Copal: The catalogue's C checker: out-of-bounds indexes, leaks, null pointers and uninitialised variables, found by reading the code, without running it.
cppcheck [--check-config] [--check-library] [-D<id>] [-U<id>] [--disable=<id>]
[--enable=<id>] [--error-exitcode=<n>] [--errorlist] [--exitcode-suppress=<spec>]
[--exitcode-suppressions=<file>] [--file-list=<file>] [--filesdir] [--force]
[--fsigned-char] [--funsigned-char] [--help] [-I<dir>] [--includes-file=<file>]
[--config-exclude=<dir>] [--config-excludes-file=<file>] [--include=<file>]
[-i<dir>] [--inconclusive] [--inline-suppr] [-j<jobs>] [-l<load>]
[--language=<language>] [--library=<cfg>] [--max-configs=<limit>]
[--max-ctu-depth=<limit>] [--platform=<type>] [--quiet] [--relative-paths=<paths>]
[--report-progress] [--report-type=<type>] [--rule=<rule>] [--rule-file=<file>]
[--showtime=<mode>] [--std=<id>] [--suppress=<spec>] [--suppressions-list=<file>]
[--suppress-xml=<.xml file>] [--template='<text>'] [--verbose] [--version] [--xml]
[--xml-version=<version>]] [file or path] ...
Use
Point it at files or a folder. By default it reports only errors it is sure of; --enable widens it to warnings, style and performance.
Examples
cppcheck src/errors only
cppcheck --enable=all src/warnings, style, performance too
cppcheck --enable=warning,performance --std=c17 src/
cppcheck --project=compile_commands.jsonwith the real flags, from bear or cmake
cppcheck --xml src/ 2> report.xml && cppcheck-htmlreport --file=report.xml --report-dir=html
Options
--enable=LIST- warning, style, performance, portability, all
--std=STD- the language standard: c11, c17, c++17...
--project=FILE- read files and flags from compile_commands.json
-I DIR- an include directory
--suppress=ID- silence one kind of message
-j N- use N threads
--xml- XML output, for the HTML report
Notes
--enable=all also reports missingInclude for system headers; --suppress=missingIncludeSystem quiets it.cppcheck-gui and cppcheck-htmlreport come with its optionals.
See also gcc, clang, valgrind
ctags Universal Ctags: index a project's definitions, so an editor can jump to them.
Devtools · command-line tool · ctags 6.2.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ctags(1) · home
needs jansson, yaml
On Copal: Stage 7 installs it: the tags file lets vim and Neovim jump to a function's definition in any language, even where no language server exists.
ctags [<options>] [<source_file(s)>]
etags [<options>] [<source_file(s)>]
Use
Run it at the top of a project; it writes a tags file. In vim or Neovim, Ctrl-] on a name jumps to where it is defined, Ctrl-T jumps back.
Examples
ctags -R .index the whole project into ./tags
ctags -R --exclude=build .leaving out a folder
ctags --list-languagesthe languages it knows
ctags -x --kinds-c=f main.cthe functions in one file, as a table
Options
-R- recurse into folders
--exclude=PATTERN- leave matching paths out
-f FILE- write to FILE instead of ./tags
--languages=LIST- index only these languages
--list-languages- list the languages
-x- print a cross-reference table instead of a file
Notes
- Re-run it after large changes: the tags file does not update itself.
- Add
tags to .gitignore; it is generated, and large.
See also nvim, vim, clangd
doxygen Generate reference documentation -- HTML, with call graphs -- from comments in source code.
Devtools · command-line tool · doxygen 1.17.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man doxygen(1) · home
On Copal: The catalogue's API documenter for C, C++ and more: comments above functions become a browsable site, with diagrams drawn by Graphviz.
Use
Make a configuration file once with -g, set the project's name and input folder in it, then run doxygen: the site appears in html/.
Examples
doxygen -gwrite a Doxyfile with every setting explained
doxygenbuild from ./Doxyfile
doxygen -g - | grep -E '^(INPUT|RECURSIVE) 'the settings to look at first
xdg-open html/index.htmlread the result
Options
-g [FILE]- write a template configuration (default Doxyfile)
-u [FILE]- update an old configuration to this version
-s- with -g or -u: leave out the explanatory comments
Notes
- Out of the box it documents only commented items;
EXTRACT_ALL = YES in the Doxyfile lists everything. HAVE_DOT = YES turns on call and include graphs, drawn with Graphviz, which is installed.- Comments it reads start with
/** or ///.
See also dot, mdbook
gdb The GNU debugger: stop a program, step through it, look at its state.
Devtools · terminal program · gdb 16.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man gdb(1) · home
needs musl-dbg, libdebuginfod, libexpat, gmp, xz-libs, mpfr4, libncursesw, python3
On Copal: Stage 7 installs it for C, C++, Rust and Go, and Neovim's F4 (Termdebug) is gdb in a split window. When a program crashes, gdb says where and why.
gdb [OPTIONS] [prog|prog procID|prog core]
Use
Start the program under gdb, set a breakpoint, run, and when it stops, look: the call stack, the variables, the next line. Build with -g first, or there is nothing to see but addresses.
Examples
gdb ./progload it, then type commands
gdb --args ./prog -v input.txtwith its arguments
gdb -q -ex run -ex bt ./progrun, and on a crash show the stack
gdb --tui ./progsource in a pane above the prompt
doas gdb -p $(pidof prog)attach to a running process
break main(inside gdb) stop at a function, or file.c:42
runstart it
next / stepthe next line / into the call
print xa variable's value
btthe call stack
continuerun on to the next stop
Options
--args PROG ARGS- pass arguments to the program
-p, --pid PID- attach to a running process
--core FILE- examine a core dump
--tui- the text interface: source, prompt, registers
-q- no banner
-ex CMD- run a gdb command at start; repeatable
Notes
- Attaching to a process needs
doas: ptrace is limited to a process's own children here (kernel.yama.ptrace_scope is 1). - Core dumps are off (
ulimit -c is 0). ulimit -c unlimited in the shell first, and a crash leaves core beside the program. - In Neovim: F9 sets a breakpoint on the current line, F4 opens Termdebug, F8 / F10 / F11 continue, step over, step into.
- For Rust,
rust-gdb prints Rust types properly; Go is better served by dlv.
See also gcc, valgrind, nvim, cgdb, lldb
just A command runner: a project's recipes -- build, test, deploy -- in a justfile.
Devtools · command-line tool · just 1.48.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man just(1) · home
On Copal: The catalogue's make for tasks rather than files: named recipes, arguments, and no tabs-versus-spaces trap.
just [--alias-style] [--allow-missing] [--ceiling] [--check] [--chooser] [--clear-shell-args]
[--color] [--command-color] [--cygpath] [--dotenv-filename] [-E|--dotenv-path] [-n|--dry-run]
[--dump-format] [--explain] [-g|--global-justfile] [--group] [--highlight] [-f|--justfile]
[--list-heading] [--list-prefix] [--list-submodules] [--no-aliases] [--no-deps] [--no-dotenv]
[--no-highlight] [--one] [-q|--quiet] [--set] [--shell] [--shell-arg] [--shell-command]
[--changelog] [--choose] [-c|--command] [--completions] [--dump] [-e|--edit] [--evaluate]
[--fmt] [--groups] [--init] [--json] [-l|--list] [--man] [-s|--show] [--summary] [--usage]
[--variables] [--tempdir] [--timestamp] [--timestamp-format] [-u|--unsorted] [--unstable]
[-v|--verbose]... [-d|--working-directory] [--yes] [-h|--help] [-V|--version] [ARGUMENTS]
Use
Write recipes in a justfile; just NAME runs one, just runs the first. Each recipe is a list of shell lines.
Examples
just --listthe recipes here
justthe default (first) recipe
just testone recipe
just deploy piwith an argument
just --dry-run buildwhat it would run
Options
-l, --list- list the recipes
-n, --dry-run- print the commands, run nothing
-f, --justfile F- use another justfile
--choose- pick a recipe from a list
-v- print each command as it runs
Notes
- A justfile recipe: a name and a colon, then the lines indented under it -- spaces or tabs, either works.
- Unlike make, just does not compare file times: a recipe always runs.
See also make
lldb LLDB Documentation
Devtools · terminal program · lldb 22.1.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man lldb(1) · home
needs musl-dbg, llvm22-libs, clang22-libs, libcurl, libedit, xz-libs, libncursesw, libpanelw
lldb [options] executable
No notes yet: the facts above are read from apk and the man page.
ltrace Watch the library calls a program makes: what it asks of libc and other libraries.
Devtools · command-line tool · ltrace 0.7.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ltrace(1) · home
needs libelf
On Copal: strace's companion one level up: where strace shows the kernel calls, ltrace shows malloc, strcmp, getenv and the rest -- which settings a program reads and what it compares.
ltrace [-e filter|-L] [-l|--library=library_pattern] [-x filter] [-S] [-b|--no-signals] [-i]
[-w|--where=nr] [-r|-t|-tt|-ttt] [-T] [-F filename] [-A maxelts] [-s strsize] [-C|--demangle]
[-a|--align column] [-n|--indent nr] [-o|--output filename] [-D|--debug mask] [-u username]
[-f] [-p pid] [[--] command [arg ...]]
ltrace -c [-e filter|-L] [-l|--library=library_pattern] [-x filter] [-S] [-o|--output
filename] [-f] [-p pid] [[--] command [arg ...]]
ltrace -V|--version
ltrace -h|--help
Use
Run a program under it; each call into a shared library prints with its arguments and return value. -c counts them instead.
Examples
ltrace ./progevery library call
ltrace -c ./proga count of calls, and their time
ltrace -e getenv ./progwhich environment variables it reads
ltrace -f -o calls.txt ./progchildren too, into a file
Options
-c- count calls instead of printing them
-e FILTER- only these calls
-f- follow child processes
-o FILE- write to FILE
-p PID- attach to a running process
-S- system calls too
Notes
- It sees calls into shared libraries only: a statically linked program shows nothing.
- Attaching with
-p needs root, like strace.
See also strace, gdb
lua-language-server The Lua language server: completion, types, and errors as you type, in any editor.
Devtools · command-line tool · lua-language-server 3.16.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
On Copal: Stage 7's server for Lua, which Neovim starts for .lua files -- the language Copal's own Neovim configuration is written in.
Use
The editor runs it; there is nothing to start by hand. From the shell, --check runs its diagnostics over a folder and reports what it finds.
Examples
lua-language-server --check=.the diagnostics for this folder
lua-language-server --check=. --check_format=prettyreadable, to stdout
Options
--check=DIR- run the diagnostics over DIR
--check_format=FMT- pretty (to stdout) or json (to a file)
Notes
- In Neovim it warns that
vim is an undefined global until told the code runs inside Neovim: a .luarc.json with {"diagnostics.globals": ["vim"]}. - A project's settings go in
.luarc.json at its root.
See also lua5.4, nvim
meson A build system: configure a project into a build folder, then build it with ninja.
Devtools · command-line tool · meson 1.11.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man meson(1) · home
needs samurai, python3
On Copal: Stage 7's Meson, for the many C, C++ and GNOME projects that build with it -- several of Copal Apps' source builds among them.
Use
Two steps, as with CMake: meson setup configures into a build folder, meson compile (or ninja -C build) builds. Options are set at setup and changed later with meson configure.
Examples
meson setup buildconfigure into ./build
meson setup build --buildtype=releaseoptimised
meson compile -C buildbuild (runs ninja)
meson test -C buildthe tests
meson configure buildevery option and its value
meson configure build -Dfoo=enabledchange one
Options
setup DIR- configure into DIR
compile -C DIR- build
test -C DIR- run the tests
install -C DIR- install (doas for /usr/local)
configure DIR- show or change options (-Dname=value)
setup --buildtype=T- debug, debugoptimized, release
setup --reconfigure- set up again in an existing folder
Notes
meson setup prints which optional dependencies it found and which it did not: that list says which features the build will have.- It writes
compile_commands.json in the build folder for clangd.
See also ninja, cmake, make
pwndbg Exploit Development and Reverse Engineering with GDB & LLDB Made Easy
Devtools · command-line tool · pwndbg 2026.02.18 · stage 12 · The application catalogue · home
needs python3, py3-capstone, py3-cparser, py3-elftools, py3-hatchling, py3-psutil, py3-pygments, py3-requests
No notes yet: the facts above are read from apk and the man page.
pylsp The Python language server: completion, go-to-definition and lint for Python, in any editor.
Devtools · command-line tool · py3-lsp-server 1.14.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs py3-docstring-to-markdown, py3-jedi, py3-lsp-jsonrpc, py3-pluggy, py3-setuptools, py3-ujson, py3-whatthepatch, py3-yapf
On Copal: Stage 7's server for Python, which Neovim and Helix start for .py files: definitions, references and hover documentation.
usage: pylsp [-h] [--tcp] [--ws] [--host HOST] [--port PORT]
[--check-parent-process] [--log-config LOG_CONFIG |
--log-file LOG_FILE] [-v] [-V]
Use
The editor runs it over stdin and stdout; there is nothing to start by hand. It finds modules as the Python it runs under does, so a project's virtual environment should be active when the editor starts.
Examples
pylsp --helpits options
. .venv/bin/activate && nvim app.pythe editor sees the venv's packages
pylsp -v --log-file /tmp/pylsp.loga verbose log, to see what it does
Options
--tcp- serve over TCP instead of stdio
--host / --port- where, with --tcp
--log-file FILE- write its log to FILE
-v- more detail in the log
Notes
- Its checks come from plugins: pyflakes (errors) and pycodestyle (style), which Copal installs with it as optionals from 24 Sep 2026.
- Settings are passed by the editor, not a file of its own.
See also python3, nvim, hx
shellcheck Find bugs in shell scripts: quoting, portability, and the traps sh is full of.
Devtools · command-line tool · shellcheck 0.11.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man shellcheck(1) · home
needs libffi, gmp
On Copal: The catalogue's shell linter, and the one Copal's own scripts are written against: most of Copal is POSIX sh, and shellcheck knows which sh a script says it is.
shellcheck [OPTIONS...] FILES...
Use
Run it on a script; each finding has a code (SC2086 and so on), a line, and an explanation. The script's first line decides the dialect it checks: #!/bin/sh is held to POSIX, #!/bin/bash allows bash.
Examples
shellcheck script.shcheck one script
shellcheck -s sh script.shas POSIX sh, whatever its first line
shellcheck -x script.shfollow the files it sources
shellcheck -f diff script.sh | patch -p1apply the fixes it can make
Options
-s SHELL- check as sh, bash, dash or ksh
-x- follow
sourced files -e CODES- exclude these codes
-S LEVEL- minimum severity: error, warning, info, style
-f FORMAT- output format: tty, gcc, json, diff
Notes
- A finding can be silenced for one line with a comment above it:
# shellcheck disable=SC2086, with the reason beside it. - Every code has a page explaining it: search "shellcheck SC2086".
See also shfmt, busybox
shfmt Format shell scripts consistently -- and parse them, which catches syntax errors.
Devtools · command-line tool · shfmt 3.13.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man shfmt(1) · home
On Copal: The catalogue's shell formatter, shellcheck's partner: one style for every script in a project, applied by a command, not by hand.
shfmt [flags] [path...]
Use
With no options it prints the script reformatted. -d shows the changes as a diff, -w writes them back. Indentation and style are options.
Examples
shfmt -d script.shwhat it would change
shfmt -w script.shchange it in place
shfmt -i 4 -w *.shfour spaces of indent
shfmt -l .list the files that are not formatted
shfmt -p -d script.shhold it to POSIX sh
Options
-d- print a diff instead of the result
-w- write the result back to the file
-l- list files whose formatting differs
-i N- indent with N spaces (0 means tabs, the default)
-p- POSIX sh only (same as -ln posix)
-ln LANG- the dialect: bash, posix, mksh, bats
-ci- indent switch cases
Notes
- A syntax error stops it with the line and column:
shfmt -d doubles as a quick check that a script parses. - It reads an
.editorconfig, so a project's indentation can live there instead of in options.
See also shellcheck
strace Watch the system calls a program makes: which files it opens, what fails, and why.
Devtools · command-line tool · strace 6.19 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man strace(1) · home
needs libdw
On Copal: The catalogue's answer to "it just says error": strace shows the file a program could not find, the permission it was refused, the address it could not reach.
strace [-ACdffhikkqqrtttTvVwxxyyYzZ] [-a column] [-b execve] [-e expr]... [-I n] [-o file]
[-O overhead] [-p pid]... [-P path]... [-s strsize] [-S sortby] [-U columns]
[-X format] [--seccomp-bpf] [--stack-trace-frame-limit=limit] [--syscall-limit=limit]
[--tips[=format]] { -p pid | [-DDD] [-E var[=val]]... [-u username] command [args] }
strace -c [-dfwzZ] [-b execve] [-e expr]... [-I n] [-O overhead] [-p pid]... [-P path]...
[-S sortby] [-U columns] [--seccomp-bpf] [--syscall-limit=limit] [--tips[=format]] {
-p pid | [-DDD] [-E var[=val]]... [-u username] command [args] }
strace --tips[=format]
Use
Run a program under it, or attach to one running. Each system call prints as a line: the call, its arguments, and its result -- a failure shows its error name, such as ENOENT (no such file).
Examples
strace -f -e trace=openat ./prog 2>&1 | grep ENOENTfiles it looked for and missed
strace -c ls /a summary: which calls, how often, how long
strace -o trace.txt -f ./progeverything, into a file
strace -e trace=network curl -s example.com >/dev/nullits network calls
doas strace -p $(pidof prog)attach to a running process
Options
-f- follow child processes too
-e trace=SET- only these calls: openat, network, file, process...
-o FILE- write the trace to FILE
-c- count calls and time instead of printing them
-p PID- attach to a running process
-s N- show strings up to N characters (default 32)
-t / -T- timestamps / time spent in each call
Notes
- Attaching to a process needs root (
ptrace_scope is 1); tracing a program you start yourself does not. strace-tui, one of its optionals, browses a saved trace file interactively.
See also ltrace, gdb, valgrind
valgrind Run a program under a checker that catches memory errors and leaks.
Devtools · command-line tool · valgrind 3.25.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man valgrind(1) · home
On Copal: On Alpine it is the memory checker: the compilers' AddressSanitizer runtime is not packaged. Stage 7 installs it where it exists -- everywhere but 32-bit ARMv6 (armhf).
valgrind [valgrind-options] [your-program] [your-program-options]
Use
Put valgrind in front of the command. The program runs perhaps twenty times slower, and every invalid read or write, use of freed memory and leak is reported with the line it came from -- if it was built with -g.
Examples
valgrind ./progmemory errors as they happen
valgrind --leak-check=full ./progand every leak, with where it was allocated
valgrind -q --leak-check=full --error-exitcode=1 ./progquiet; fail a test on error
valgrind --track-origins=yes ./progwhere an uninitialised value came from
valgrind --tool=callgrind ./progwhere the time goes, by function
Options
--leak-check=full- report each leak in detail
--show-leak-kinds=all- include "still reachable" blocks
--track-origins=yes- trace uninitialised values to their source (slower)
--error-exitcode=N- exit N if errors were found
--tool=NAME- memcheck (default), massif, callgrind, cachegrind, helgrind
-q- only the errors
--log-file=FILE- report to FILE instead of the terminal
Notes
- Read the first error first. Later ones are often its consequences.
- "definitely lost" is a real leak; "still reachable" is memory held at exit, usually harmless.
- Build with
-g -O0 (or -O1) for readable reports; optimised code reports lines that do not match the source.
See also gdb, gcc, clang
Discs
7z 7-Zip: pack and unpack .7z, zip, tar and more, and extract rar, iso and dozens of others.
Discs · command-line tool · 7zip 26.01 · stage 10 · Wireless, audio, capture and disks · home
On Copal: The catalogue's universal archiver: the best compression of the common formats, strong encryption, and it opens nearly any archive someone sends you -- rar included.
Usage: 7zz <command> [<switches>...] <archive_name> [<file_names>...] [@listfile]
<Commands>
a : Add files to archive
Use
A command letter, the archive, then files. x extracts with folders, a adds, l lists. It detects the format of what it opens.
Examples
7z x archive.rarextract, keeping folders
7z l archive.7zlist the contents
7z a backup.7z ~/Documentsa new .7z of a folder
7z a -p -mhe=on secret.7z plans/encrypted, names hidden too
7z x image.iso -oiso-filesthe files inside an ISO
7z t archive.ziptest it for damage
Options
a- add to an archive (creating it)
x- extract with full paths
e- extract everything into one folder
l- list
t- test integrity
-o DIR- extract into DIR (written -oDIR, no space)
-p- set or ask for a password
-mx=N- compression level, 0 to 9 -m{...} other method settings: -mhe=on encrypts the file names too (.7z)
Notes
- The command here is
7z; guides that say 7za or 7zr mean the same program. -o takes its folder with no space: -oout, not -o out.- It reads rar archives but cannot create them.
See also zip, bsdtar, unarj
abcde A Better CD Encoder: rip a CD, look up its track names, encode and tag, in one command.
Discs · command-line tool · abcde 2.9.3 · stage 12 · The application catalogue · man abcde(1) · home
needs bash, cd-discid, eyed3, perl-webservice-musicbrainz
On Copal: The catalogue's CD-to-music-library tool: cdparanoia to rip, a database lookup for the names, an encoder for FLAC, Ogg or MP3.
abcde [options] [tracks]
Use
Insert the CD and run it. It looks up the disc, asks you to confirm the names, rips every track and encodes them into folders by artist and album.
Examples
abcderip and encode, with the defaults
abcde -o flacto FLAC
abcde -o flac,oggtwo formats at once
abcde -N -o flacno questions (unattended)
abcde -c ~/.abcde.confwith your own settings
Options
-o FORMATS- output formats: flac, ogg, mp3, opus...
-N- non-interactive: accept the lookup's answer
-d DEV- the CD drive
-c FILE- another configuration file
-x- eject the CD when done
Notes
- Settings go in
~/.abcde.conf: OUTPUTTYPE, OUTPUTDIR, the naming pattern. - Each format needs its encoder. Its default, Ogg, needs
oggenc (vorbis-tools), which abcde does not pull in: the catalogue row brings it and flac from 24 Sep 2026. MP3 needs lame. - Not on 32-bit ARMv7: its row is gated off there.
See also cdparanoia, cmus
bsdtar libarchive's tar: reads almost any archive -- tar, zip, 7z, rar, iso, cpio, deb, rpm, xar.
Discs · command-line tool · libarchive-tools 3.8.7 · stage 12 · The application catalogue · man bsdtar(1) · home
needs acl-libs, libbz2, libcrypto3, libexpat, lz4-libs, xz-libs, zlib, zstd-libs
On Copal: The catalogue's universal unpacker. One command extracts whatever format someone sent, detecting it and its compression by itself.
tar [bundled-flags ⟨args⟩] [⟨file⟩ | ⟨pattern⟩ ...]
tar {-c} [options] [files | directories]
tar {-r | -u} -f archive-file [options] [files | directories]
tar {-t | -x} [options] [patterns]
Use
The tar options, on any format: -t lists, -x extracts, -c creates. Compression is detected when reading; when creating, -a picks it from the file name.
Examples
bsdtar -tf archive.ziplist any archive
bsdtar -xf image.iso -C out/extract, here an ISO, into out/
bsdtar -xf package.rpmthe files inside an .rpm
bsdtar -caf backup.tar.zst ~/notescreate, compression from the name
bsdtar -cf - folder | ssh pi 'bsdtar -xf - -C /tmp'copy a tree over ssh
Options
-t- list the contents
-x- extract
-c- create
-f FILE- the archive (- for stdin or stdout)
-C DIR- change into DIR first
-a- with -c: compression from the suffix (.gz .xz .zst .zip ...)
-v- name each file
-z / -j / -J- gzip / bzip2 / xz, when creating without -a
Notes
tar on Copal is GNU tar; bsdtar is the one that also opens zip, 7z, ISO and rar.- It reads rar, but writes only the formats it lists in its manual: tar, zip, 7z, iso, cpio and others.
See also 7z, zip, xorriso, rpm, dpkg
cdparanoia Rip audio CDs to WAV files, correcting for scratches and drive errors.
Discs · command-line tool · cdparanoia 10.2 · stage 12 · The application catalogue · man cdparanoia(1) · home
needs cdparanoia-libs
On Copal: The catalogue's CD ripper: it reads each sector until it is sure, which is what makes a rip from a worn disc sound like the disc.
cdparanoia [options] span [outfile]
Use
With a CD in the drive, rip every track, or chosen ones, to WAV files in the current folder. The progress line shows how hard it had to work.
Examples
cdparanoia -Qthe tracks on the disc
cdparanoia -Bevery track, as track01.cdda.wav...
cdparanoia 3 song.wavtrack 3 only
cdparanoia -B -d /dev/sr1from another drive
Options
-B- batch: every track, each to its own file
-Q- query the disc and print its table of contents
-d DEV- the drive to use
-X- abort on a skip rather than filling it in
-z- never skip: retry an unreadable sector forever
Notes
- For MP3, FLAC or Ogg with names and tags,
abcde runs cdparanoia and an encoder together. - The drive needs the
cdrom group.
See also abcde, cdrdao
cdrdao Write CDs in disc-at-once mode: audio CDs, gapless, from a TOC or CUE file.
Discs · command-line tool · cdrdao 1.2.6 · stage 12 · The application catalogue · man cdrdao(1) · home
On Copal: The catalogue's audio CD writer: disc-at-once keeps the gaps between tracks exactly as described, which track-at-once cannot.
cdrdao
{show-toc|toc-info|toc-size|read-toc|read-cd|read-cddb|show-data|read-test|disk-info|discid|msinfo|drive-info|unlock|scanbus|simulate|write|copy|blank}
[--device device] [--source-device device] [--driver driver-id] [--source-driver driver-id]
[--simulate] [--speed writing-speed] [--blank-mode mode] [--datafile file] [--read-raw]
[--read-subchan [--no-mode2-mixed] mode] [--tao-source] [--tao-source-adjust link-blocks]
[--fast-toc] [--buffers buffer-count] [--multi] [--overburn] [--eject] [--swap] [--session]
[--force] [--reload] [--keepimage] [--on-the-fly] [--paranoia-mode mode] [--with-cddb]
[--cddb-servers server-list] [--cddb-timeout timeout] [--cddb-directory directory] [--tmpdir
directory] [--keep] [--save] [-n] [-v verbose-level] toc-file
Use
Describe the disc in a table of contents (a .toc or .cue file) that lists the WAV files, then write it. It can also copy a whole CD.
Examples
cdrdao scanbusthe drives it can see
cdrdao write --device /dev/sr0 disc.tocburn from a TOC
cdrdao write --device /dev/sr0 --speed 8 disc.cueslower, from a CUE
cdrdao read-cd --device /dev/sr0 copy.tocread a whole CD to image + TOC
cdrdao show-toc disc.toccheck a TOC before burning
Options
write TOC- burn the disc described in TOC
read-cd TOC- read a CD into an image and a TOC
show-toc TOC- print what a TOC describes
scanbus- list drives
--device DEV- the drive (/dev/sr0)
--speed N- the writing speed
--eject- eject when done
Notes
- A TOC file is plain text: one
TRACK AUDIO block per track, each with FILE "track01.wav" 0. - Access to the drive is the
cdrom group's.
See also cdparanoia, abcde, xorriso
cdw A terminal front end for burning CDs and DVDs: data discs, ISO images, erasing.
Discs · terminal program · cdw 0.8.1 · stage 12 · The application catalogue · man cdw(1) · home
needs cdrkit, libburn, libcdio, libformw, libintl, libmenuw, libncursesw, libpanelw
On Copal: The catalogue's disc burner for a machine with no desktop, driving the command-line burning tools through menus.
cdw [--help] [--version] [--enable-dvd-rp-dl] [--escdelay=X]
Use
Start it with a burner attached; pick files or an ISO image from the menus, and write them. It calls the underlying tools (xorriso and others) and shows what they report.
Examples
cdwthe menus
lsblk -o NAME,TYPE,MODEL | grep romis there a drive (sr0)?
F1 ? (in cdw) help: the keys of the current window
Enter choose
Q quit
Options
Notes
- Writing needs access to the drive,
/dev/sr0, which the group cdrom owns: doas adduser $USER cdrom, then log in again. - Its settings, including which drive and which tools, are in its configuration window and
~/.cdw/cdw.conf.
See also xorriso, cdrdao, cdparanoia
dpkg Look inside Debian and Ubuntu packages: list, inspect and unpack .deb files.
Discs · command-line tool · dpkg 1.23.7 · stage 12 · The application catalogue · man dpkg(1) · home
needs tar, xz, libbz2, libmd, zlib
On Copal: The catalogue's way to open a .deb on Alpine, to see what it holds or take files out of it. Not for installing: Alpine's packages are apk's.
dpkg [option...] command
Use
dpkg-deb does the looking: -c lists the files, -I shows the package's information, -x extracts the files into a folder.
Examples
dpkg-deb -I package.debname, version, dependencies, description
dpkg-deb -c package.debthe files it contains
dpkg-deb -x package.deb out/extract the files into out/
dpkg-deb -e package.deb ctl/its control files and install scripts
dpkg -c package.debthe same as dpkg-deb -c
Options
-c, --contents- list the contents (as dpkg-deb -c)
-I, --info- show the package information
-x DIR- extract the files into DIR (with dpkg-deb)
-e DIR- extract the control files (with dpkg-deb)
Notes
dpkg -i would install into a Debian database that nothing here reads: do not. The program inside is built for glibc and will not run on musl as it is.bsdtar -xf package.deb shows the layers: control.tar.* and data.tar.*, the second holding the files.
See also rpm, bsdtar, apk
mksquashfs Pack a folder into a SquashFS image -- compressed, read-only, mountable -- and unsquashfs to unpack one.
Discs · command-line tool · squashfs-tools 4.7.5 · stage 12 · The application catalogue · man mksquashfs(1) · home
needs lz4-libs, xz-libs, lzo, zlib, zstd-libs
On Copal: The catalogue's SquashFS tools: the format of live systems and of Alpine's own boot images, and a way to keep a large folder compressed yet browsable.
mksquashfs source1 source2 ... FILESYSTEM [OPTIONS] [-e list of exclude dirs/files]
Use
mksquashfs FOLDER IMAGE writes a compressed image of the folder. Mount it read-only to use the files in place, or unsquashfs to get them back.
Examples
mksquashfs ~/photos photos.sqfs -comp zstdan image, zstd-compressed
unsquashfs -l photos.sqfslist what is inside
unsquashfs -d restored photos.sqfsunpack into restored/
doas mount -o loop,ro photos.sqfs /mntbrowse it in place
Options
-comp ALG- compression: gzip, xz, lz4, zstd, lzo
-b SIZE- block size (larger compresses better)
-e NAMES- exclude these files
-noappend- overwrite the image rather than add to it
-processors N- threads to use
Notes
- Without
-noappend, a second run adds to an existing image rather than replacing it. - The image is read-only by design; to change it, unpack, edit, and pack again.
See also bsdtar, xorriso
rpm Look inside Red Hat, Fedora and SUSE packages: list, inspect and unpack .rpm files.
Discs · command-line tool · rpm 4.19.1.1 · stage 12 · The application catalogue · man rpm(8) · home
needs rpm-scripts, acl-libs, libarchive, libbz2, libcap2, libcrypto3, libdw, libelf
On Copal: The catalogue's way to open a .rpm on Alpine -- to read what a package holds, or take one file out of it. Not for installing: Alpine's packages are apk's.
QUERYING AND VERIFYING PACKAGES:
rpm {-q|--query} [select-options] [query-options]
rpm --querytags
rpm {-V|--verify} [select-options] [verify-options]
INSTALLING, UPGRADING, AND REMOVING PACKAGES:
rpm {-i|--install} [install-options] PACKAGE_FILE ...
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
...
Use
Query a package file with -qp and a second letter for what to show. To unpack it, turn it into a cpio stream with rpm2cpio.
Examples
rpm -qpi package.rpmname, version, description
rpm -qpl package.rpmthe files it contains
rpm -qp --scripts package.rpmwhat it would run on install
rpm2cpio package.rpm | cpio -idmvunpack it into this folder
bsdtar -xf package.rpmthe same, in one step
Options
-q, --query- query mode
-p, --package- query a package file (not an installed package)
-l, --list- list its files
-i- with -q: its information
--scripts- with -q: its install scripts
Notes
rpm -i would try to install into an rpm database Alpine does not use: do not. A program packaged only as .rpm needs rebuilding for Alpine, or a Flatpak.- A .rpm is built for glibc; its binaries will not run on musl as they are.
See also dpkg, bsdtar, apk
unarj List, test and extract .arj archives -- the DOS-era format.
Discs · command-line tool · unarj 2.65 · stage 12 · The application catalogue · home
On Copal: The catalogue's key to old archives: software and files from the 1990s, BBS downloads and old disk images often arrive as .arj.
Use
A command letter, then the archive. It only reads: it cannot make .arj files.
Examples
unarj l old.arjlist the contents
unarj t old.arjtest it for damage
unarj x old.arjextract, keeping folders
unarj e old.arjextract everything into this folder
Options
l ARCHIVE- list
t ARCHIVE- test
x ARCHIVE- extract with paths
e ARCHIVE- extract without paths
Notes
- It is the free demonstration version: it reads ordinary archives but not multi-volume or password-protected ones.
7z x old.arj handles more. - Names from DOS come in capitals and 8.3 form, as they were stored.
See also 7z, bsdtar, zip
xorriso Make ISO 9660 images and burn them: data discs, bootable images, and updates to both.
Discs · command-line tool · xorriso 1.5.8 · stage 12 · The application catalogue · man xorriso(1) · home
needs libisoburn
On Copal: The catalogue's ISO tool, and the one that makes bootable images: its -as mkisofs mode takes the options of the classic mkisofs.
xorriso [settings|actions]
Use
Build an image from a folder, burn an image to a disc, or list and extract what an image holds. -as mkisofs and -as cdrecord accept the older tools' options, which is what most recipes online use.
Examples
xorriso -as mkisofs -o backup.iso -J -R ~/Documentsan ISO from a folder
xorriso -indev image.iso -ls /what is in an image
xorriso -osirrox on -indev image.iso -extract / out/unpack it
xorriso -as cdrecord -v dev=/dev/sr0 image.isoburn it to a disc
xorriso -devicesthe burners it sees
Options
-as mkisofs- behave like mkisofs (-o OUT, -J, -R, -V LABEL)
-as cdrecord- behave like cdrecord (dev=, -v, blank=)
-indev FILE- read an existing image or disc
-outdev FILE- write to an image or disc
-ls PATH- list a folder inside the image
-extract A B- copy A from the image to B (with -osirrox on)
-devices- list optical drives
Notes
-J -R add Joliet and Rock Ridge: long names for Windows and Unix. Without them names are cut to 8.3 capitals.- Burning needs the
cdrom group, which owns /dev/sr0.
See also cdw, cdrdao, bsdtar
zip Make .zip archives -- and, with unzip, list and extract them.
Discs · command-line tool · zip 3.0 · stage 12 · The application catalogue · man zip(1) · home
needs unzip
On Copal: The catalogue's zip pair: the archive format every other system opens without asking, for sending folders to Windows and Mac users.
zip [-aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$] [--longoption ...] [-b path] [-n suffixes] [-t date]
[-tt date] [zipfile [file ...]] [-xi list]
zipcloak (see separate man page)
zipnote (see separate man page)
zipsplit (see separate man page)
Note: Command line processing in zip has been changed to support long options and handle all
options and arguments more consistently. Some old command lines that depend on command line
inconsistencies may no longer work.
Use
zip ARCHIVE FILES adds files to an archive, creating it if needed; -r takes whole folders. unzip extracts, unzip -l lists.
Examples
zip -r photos.zip ~/Pictures/tripa folder, recursively
zip notes.zip *.txtsome files
zip -e secret.zip plan.txtwith a password
unzip -l photos.zipwhat is inside
unzip photos.zip -d ~/restoreextract into a folder
Options
-r- include folders, recursively
-e- encrypt, asking for a password
-9- best compression (-1 fastest)
-u- update: add only changed files
-x PATTERN- leave matching files out
-q- quiet
Notes
- zip's own password encryption is weak. For real secrecy use
7z a -p -mhe=on, which is AES-256 and hides the file names too. zip -r stores paths as given: zip -r a.zip /home/you/x stores the full path, so change into the folder first for short ones.
See also unzip, 7z, bsdtar
Games
adventure Colossal Cave Adventure: the first text adventure, from 1977.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man adventure(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games (bsd-games): the ancestor of Zork and of every text adventure since, typed a command at a time.
Use
Read the description, type a command of one or two words -- go north, get lamp, open grate -- and read what happens. Map the cave on paper as you go; that is how it was meant to be played.
Examples
adventurestart (answer "no" to the instructions, or read them)
enter building (in the cave) move, by direction or by place
get lamp take things; inventory what you carry
look describe the place again
save stop here, to continue later
quit end the game, with a score
Options
Notes
- The first thing to do is take the lamp. The cave is dark.
- It understands the first five letters of a word:
inven is inventory. help and info are commands too: the game explains itself.
See also frotz, nethack
angband Angband: a hundred-level descent to Morgoth, in the lineage of Moria.
Games · terminal program · angband 4.2.5 · stage 12 · The application catalogue · home
needs sdl2, sdl2_image, sdl2_mixer, sdl2_ttf, libncursesw
On Copal: The catalogue's long-form roguelike: a character built over many hours, a town to return to, and the dungeon from Tolkien's Moria onward.
Use
Create a character, buy supplies in the town, and descend. Levels are made afresh every time you take the stairs, so going back up and down is normal. ? is the help, Enter a menu of every command.
Examples
angbandcontinue, or make a character
angband -na new character
angband -lthe savefiles there are
angband -uGandalfplay the savefile named Gandalf
arrows / hjkl (in angband) move
Enter the menu of every command
g i w pick up / inventory / wield
< > stairs up / down
Ctrl-X save and quit
Options
-n- a new character (overwrites the default savefile, without -u)
-u NAME- use the savefile NAME
-l- list the savefiles
-c- choose a savefile from a menu
-w- bring a dead character back (marks the save)
Notes
- Your saves and settings are in
~/.angband, not in /usr/share. -n without -u replaces the default character. Name a new one: angband -n -uSomeone.- It comes from Alpine's testing repository (
angband@testing).
See also zangband, nethack, brogue
asciiquarium An aquarium in the terminal: fish, sharks, a castle and bubbles, animated.
Games · terminal program · asciiquarium 1.1 · stage 12 · The application catalogue · home
needs perl, perl-term-animation
On Copal: One of the catalogue's toys: something alive in a spare terminal or a tmux pane, and a quick test of a terminal's colours and speed.
Use
Run it, watch, press q to leave. It fills the terminal at whatever size it is, and redraws when the window changes.
Examples
asciiquariumwatch
q (while running) quit
p pause
r redraw
Options
Notes
- It is a Perl program: the first frame takes a moment on a Pi.
- It ignores
--help and simply starts.
See also cmatrix, cbonsai
atc Air Traffic Control: route planes through your airspace without a collision.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man atc(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games, and the best of them -- unplayable until you have read man atc, and excellent afterwards.
atc [-u?lstp] [-gf game name] [-r random seed]
Use
Planes enter at the edges; guide each to its exit or airport at the right altitude, and keep them apart. Every command starts with the plane's letter, then the action and its value, and Enter sends it; ? lists what may come next at any point.
Examples
atcthe default airspace
atc -lthe airspaces there are
atc Killera harder one
atc -sthe scores
man atcread this first
Options
-l- list the scenarios
-s- print the score table
SCENARIO- play that airspace: Default, Atlantis, Killer, OHare
Notes
ba5 sends plane b to 5000 feet; btd turns it to heading east. Directions are the eight keys around s: w north, e north-east, d east, round to q north-west.- Planes enter at 7000 feet and must leave through their exit at 9000, or land at their airport by going to 0 directly over it.
See also robots, snake
brogue Brogue: a roguelike made to be learned -- twenty-six levels, no classes, beautiful in a terminal.
Games · terminal program · brogue 1.15.1 · stage 12 · The application catalogue · home
needs sdl2, sdl2_image
On Copal: The catalogue's most approachable roguelike: fewer keys than NetHack, a mouse that works, and a dungeon that shows you what it is doing.
Use
Descend twenty-six levels to the Amulet of Yendor and back out. You build your character from what you find, not from a class. The mouse moves you and describes what you point at; ? lists the keys.
Examples
broguethe menu
brogue -na new game at once
brogue -s 12345a game from a seed (share it)
brogue --scoresthe high scores
brogue -v game.broguerecwatch a recording
arrows / hjkl (in brogue) move; x explore automatically
i s inventory / search; > descend
? every key; Q quit
Options
-n- a new game, skip the menu
-s SEED- a new game from SEED
-o FILE- open a saved game
-v FILE- view a recording
--scores- print the scores
--size N- font size, 1 to 20 (in a window build)
Notes
x explores the level for you until something interesting happens; most of the game is choosing when to stop.- Every game is recorded; recordings, saves and scores are kept in
~/.local/share/brogue.
See also nethack, angband
cbonsai Grow a bonsai tree in the terminal, slowly, or print one.
Games · command-line tool · cbonsai 1.4.2 · stage 12 · The application catalogue · man cbonsai(6) · home
needs libncursesw, libpanelw
On Copal: One of the catalogue's toys: a different tree every time, as a screensaver or as the first thing a new shell prints.
cbonsai [OPTION]...
Use
With no options it draws a finished tree. -l shows it growing; -S is the screensaver, growing tree after tree until a key is pressed.
Examples
cbonsaia tree, finished
cbonsai -lwatch it grow
cbonsai -Sscreensaver: one tree after another
cbonsai -p -m "$(fortune -s)"print a tree with a saying beside it
Options
-l, --live- show each step of growth
-t, --time=SECS- the delay between steps with -l
-i, --infinite- keep growing trees
-S, --screensaver- -l and -i together, quit on any key
-m, --message=STR- a message beside the tree
-p, --print- print the tree and leave it on the terminal
-L, --life=N- how big it grows (default 32)
Notes
-p makes it usable in a shell's start-up: the tree stays on screen above the prompt.
See also asciiquarium, cmatrix, fortune
cmatrix The falling green characters of The Matrix, in the terminal.
Games · terminal program · cmatrix 2.0 · stage 12 · The application catalogue · man cmatrix(1) · home
needs libncursesw
On Copal: One of the catalogue's toys, and a screensaver for a console with nothing else to show.
cmatrix [-abBflohnsmVx] [-u update] [-C color]
Use
Run it and watch; q quits. Keys change it while it runs: speed, colour, boldness.
Examples
cmatrixwatch
cmatrix -sscreensaver: any key ends it
cmatrix -b -C bluebold, in blue
cmatrix -u 2faster (0 fastest, 9 slowest)
cmatrix -asmooth, asynchronous columns
0-9 (while running) speed
! @ # $ % ^ & ) red, green, yellow, blue, magenta, cyan, white, ...
q quit
Options
-s- screensaver mode: exit on the first key
-b / -B- some / all characters bold
-C COLOR- green, red, blue, white, yellow, cyan, magenta, black
-u N- the delay, 0 to 9
-a- asynchronous scroll
-l- Linux console mode, with the matrix font
-m- lambda mode: every character is a lambda
Notes
-l changes the console font and only makes sense on a text console, not in a terminal window.
See also asciiquarium, cbonsai
figlet Print text in large letters made of characters.
Games · command-line tool · figlet 2.2.5 · stage 12 · The application catalogue · man figlet(6) · home
On Copal: One of the catalogue's toys, and useful: a banner at the top of a script's output, a login message, a heading in a README.
figlet [ -cklnoprstvxDELNRSWX ] [ -d fontdirectory ]
[ -f fontfile ] [ -m layoutmode ]
[ -w outputwidth ] [ -C controlfile ]
[ -I infocode ] [ message ]
Use
Give it the words; it prints them large. -f chooses the font; showfigfonts shows them all.
Examples
figlet Copalbig text, the standard font
figlet -f slant Copalanother font
figlet -c -w 80 'Hello, world'centred on 80 columns
showfigfonts | lessevery font, as a sample
echo Build done | figletfrom a pipe
Options
-f FONT- the font: standard, slant, banner, big, small, script...
-c- centre the text
-r- right-justify it
-w N- the output width
-t- use the terminal's width
-k- kerning: letters close, not overlapping
Notes
- The fonts are in
/usr/share/figlet/fonts; figlist names them. - A long line wraps at 80 columns unless
-w or -t says otherwise.
See also fortune, cbonsai
fortune Print a random saying: quotations, jokes, limericks, Star Trek.
Games · command-line tool · fortune 0.1 · stage 12 · The application catalogue · man fortune(6) · home
needs libbsd
On Copal: One of the catalogue's toys, and a tradition: the saying a new terminal greets you with.
fortune [-aefilosw] [-m pattern] [[N%] file/directory/all]
Use
Run it and a saying is printed. Name a collection to choose from it alone; -s keeps it to a line or two.
Examples
fortunea saying
fortune -sa short one
fortune startrekfrom one collection
fortune -m 'computer'every saying that matches
fortune -fthe collections, and their sizes
Options
-s- short sayings only
-l- long ones only
-m PATTERN- print every saying matching PATTERN
-i- ignore case, with -m
-f- list the files it would choose from
-o- only the potentially offensive ones
-a- all of them, offensive included
Notes
- The collections are in
/usr/share/fortune: fortunes, fortunes2, limerick, recipes, startrek, zippy. - To greet every new terminal, add
fortune -s to the end of ~/.profile.local.
See also cbonsai, figlet
frotz A Z-machine interpreter: plays Infocom's text adventures and everything written for it since.
Games · command-line tool · frotz 2.55 · stage 12 · The application catalogue · man frotz(6) · home
needs libao, libmodplug, libncursesw, libsamplerate, libsndfile
On Copal: The catalogue's interactive-fiction player. It ships with no stories; thousands are free on the Interactive Fiction Archive, and Zork I to III are freely distributed.
frotz [options] file [blorb_file]
At least one file must be specified on the command line. This can be either a plain Z-code
file or a Blorb file. A Z-code file is a compiled executable for the Z-Machine. A Blorb
file contains audio, graphics, and other things in addition to the game wrapped up into a
single file. It can also optionally contain the Z-Machine executable. If a plain Z-code
file is supplied, then Frotz will check for a Blorb file with the same base name but an
extension of .blb, .blorb, or .zblorb and load it if found.
If the file supplied on the command line is a Blorb file, then Frotz will check to see if a
Z-code file is contained within. If not found, then Frotz will complain and exit.
An alternatively-named Blorb file can be supplied as the optional second parameter to the
command line invocation.
...
Use
Give it a story file -- .z3, .z5, .z8 -- and play by typing commands. save and restore work inside the story, to a file you name.
Examples
frotz zork1.z5play
frotz -w 80 story.z8at a fixed width
frotz -d story.z5no colours
look inventory (in the story) the usual commands
save restore to and from a file you name
undo take back the last move, in stories that allow it
quit leave
Options
-d- disable colour
-w N- the screen width
-h N- the screen height
-l N- the left margin
-L FILE- load a saved game at start
-e- enable sound
Notes
- Where to find stories: ifarchive.org (the Interactive Fiction Archive), and ifdb.org to choose one. Most are one file; download it and play.
- Glulx stories (
.gblorb, .ulx) need a different interpreter; frotz is the Z-machine only.
See also adventure
hangman Hangman, against the system dictionary.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man hangman(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games. It draws its words from /usr/share/dict/words, which Copal links to the English word list.
hangman [-d wordlist] [-m minlen]
Use
Guess the hidden word a letter at a time; seven wrong guesses and the figure is complete.
Examples
hangmanplay, words from the system dictionary
hangman -m 8only words of 8 letters or more
hangman -d words.txtwords from your own list
Options
-d FILE- the word list (default /usr/share/dict/words)
-m N- the shortest word length
Notes
- "unable to open dictionary file /usr/share/dict/words" means the word list is missing: stage 18 links it to
american-english from words-en.
See also fortune, robots
klondike Klondike solitaire, in a terminal, with the keyboard.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man klondike(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games: patience for a terminal session.
Use
The standard patience: build the foundations up by suit from the aces, moving cards between the seven columns in descending, alternating colours. Keys name the piles; the screen lists them.
Examples
klondikeplay
Options
Notes
- The keys are shown on the screen as you play;
? if they are not. ttysolitaire is the same game drawn with box characters, and it counts passes through the deck.
See also ttysolitaire
moon-buggy Drive a buggy across the moon, jumping craters and blasting rocks -- in a terminal.
Games · terminal program · moon-buggy 1.0.51 · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man moon-buggy(6) · home
needs libncursesw
On Copal: The store's terminal arcade game: one key to jump, one to fire, and it gets faster. Playable anywhere, over SSH included.
moon-buggy [-hnsV] [--help] [--no-title] [--show-scores] [--version]
Use
The buggy drives itself; jump over the craters with Space and clear rocks with the laser. The timing of a jump is fixed, so the skill is choosing when.
Examples
moon-buggyplay
moon-buggy -nskip the title screen
moon-buggy -sthe high scores, and exit
Space j (in the game) jump
a l fire the laser
q quit (the score is kept)
Options
-n, --no-title- no title screen
-s, --show-scores- print the high scores and exit
-m, --mesg- keep other users' messages off the screen
Notes
- A jump can only start with the wheels on the ground: jumping early is the usual way to land in the next crater.
- It comes from Alpine's testing repository (
moon-buggy@testing).
See also robots, snake, nethack
nethack NetHack: the deepest of the roguelikes -- a dungeon of letters, and everything interacts.
Games · terminal program · nethack 3.6.7 · stage 12 · The application catalogue · man nethack(6) · home
needs libncursesw
On Copal: The catalogue's first roguelike and its deepest: a game people have played for thirty-five years, in any terminal, over SSH included.
nethack [ -d directory ] [ -n ] [ -p profession ] [ -r race ] [ -[DX] ] [ -u playername ] [
-dec ] [ -ibm ] [ --showpaths ] [ --version[:paste] ]
nethack [ -d directory ] -s [ -v ] [ -p profession ] [ -r race ] [ playernames ]
Use
Pick a role, a race and a name, and descend to retrieve the Amulet of Yendor. You are the @. Every key is a command; ? lists them. Death is permanent, and there is a lot of it.
Examples
nethackplay
nethack -u Rodneyplay as Rodney (and resume his save)
nethack -sthe high scores
h j k l y u b n (in nethack) move, including diagonally
i , d inventory / pick up / drop
spray search / pray (once in a while)
S save and quit; ? help
Options
-u NAME- the character's name; a saved game of that name resumes
-s- show the scores
-p ROLE- choose the role: Valkyrie, Wizard, Samurai...
-X- explore mode: no death, no score
Notes
- Options go in
~/.nethackrc: OPTIONS=number_pad:1 for the numeric keypad, OPTIONS=color, OPTIONS=autopickup,pickup_types:$. S saves; next time, the same name picks up where you left.- A Valkyrie is the gentlest start.
See also brogue, angband, zangband
robots Escape the robots: every move, they step toward you, and collide into junk.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man robots(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games: a five-minute puzzle, in any terminal, with a score table.
Use
Robots (+) move one step toward you (@) each turn. When two collide, or one walks into a junk heap (*), they die: a point each. Clear the field and the next one starts. You have no weapon, only a teleporter.
Examples
robotsplay
h j k l y u b n (in the game) move, diagonals included
. or Space stay where you are for a turn
t teleport, somewhere random
q quit
Options
Notes
- Standing still is a move: the robots close in and, lined up right, pile into each other.
- Scores are shared in
/usr/share/bsdgames by the group users; Copal links the path the game expects and adds you to the group from 24 Sep 2026. Before that, a score was shown and then lost.
See also snake, atc, nethack
sl A steam locomotive crosses the screen -- for when you typed sl instead of ls.
Games · command-line tool · sl 5.02 · stage 12 · The application catalogue · man sl(1) · home
needs libncursesw
On Copal: One of the catalogue's toys: the classic punishment for a typo. It cannot be interrupted, which is the point.
sl [ -alFc ]
Use
Mistype ls as sl, and wait.
Examples
sla train
sl -la little one
sl -Fit flies
sl -aan accident
Options
-a- an accident: people cry for help
-l- a little locomotive
-F- it flies
-c- C51 instead of D51
Notes
- Ctrl-C does not stop it. It ends when the train has passed.
See also cmatrix, asciiquarium
snake Collect the money and reach the exit, with a snake after you.
Games · terminal program · bsd-games 3.3 · stage 4 · X.Org, i3, a terminal and a browser · man snake(6) · home
needs libncursesw
On Copal: Part of the catalogue's BSD games: not the phone game, the older one, where you are the one being chased.
snake [width height] [-s]
Use
You are the @. Pick up the money ($) -- a new one appears each time -- and leave through the exit (#) before the snake (S and its s body) catches you. As you get richer, the snake gets hungrier.
Examples
snakeplay, on the whole screen
snake 60 20a smaller field: width, height
snake -sthe scores, and exit
h j k l or arrows (in the game) move
Space warp out of a tight spot, at a price
Options
WIDTH HEIGHT- the size of the field (default: the screen)
-s- print the scores and exit
Notes
- Only leaving by the exit scores. Being eaten is worth nothing.
- Scores go in the shared table (
/usr/share/bsdgames), kept from 24 Sep 2026 for members of users, which Copal adds you to.
See also robots, atc
ttysolitaire Klondike solitaire drawn with box characters, played with vi keys.
Games · terminal program · tty-solitaire 1.4.1 · stage 12 · The application catalogue · home
needs libncursesw
On Copal: The catalogue's nicer-looking terminal patience: real card shapes in any terminal, over SSH included.
Use
Standard Klondike: build down in alternating colours on the seven columns, up by suit from the aces on the foundations. The cursor moves between piles; a card is picked up and put down with one key.
Examples
ttysolitaireplay
ttysolitaire -p 1one pass through the deck: harder
ttysolitaire --four-color-decka colour per suit
Options
-p, --passes N- passes through the deck (default 3)
--four-color-deck- a distinct colour for each suit
--no-background-color- no green table
Notes
- The command is
ttysolitaire, one word; the package is tty-solitaire. - It installs no documentation; the keys are in the README at github.com/mpereira/tty-solitaire.
See also klondike
zangband ZAngband: Angband with a wilderness, towns, and Zelazny's Amber above the dungeon.
Games · terminal program · zangband 2.7.5.1 · stage 12 · The application catalogue · home
needs ncurses, libncursesw
On Copal: The catalogue's sprawling Angband variant: a whole overworld of towns and dungeons rather than one town and one descent.
Use
Make a character, walk the wilderness between towns, and pick which dungeons to take on. ? is the help and = the options, as the title screen says.
Examples
zangbandplay
arrows / hjkl (in zangband) move
? = help / options
g i w pick up / inventory / wield
< > stairs up / down
Ctrl-X save and quit
Options
-n- a new character
-u<name>- play the character NAME: zangband -uRodney
Notes
- It starts only for a member of the group
users, which owns its score and save directories: otherwise "Cannot create the '/usr/lib/zangband/apex/scores.raw' file!" and a fatal error. Copal adds you from 24 Sep 2026; before that, doas adduser $USER users, then log out and in. - Saves are shared in
/usr/lib/zangband/save, by character name.
See also angband, nethack, brogue
Internet
elinks A text web browser with tabs, menus, and Gopher as well as the web.
Internet · terminal program · elinks 0.19.1 · stage 12 · The application catalogue · man elinks(1) · home
needs libcrypto3, libcurl, libexpat, gpm-libs, libidn2, libintl, libssl3, zlib
On Copal: One of the catalogue's text browsers, kept at every level: a few hundred kilobytes, it works over SSH with no display, and it opens gopher:// links the smallweb section points at.
elinks [OPTION]... [URL]...
Use
Browse in the terminal with the menus and tabs a graphical browser has. Esc opens the menu bar, so every command can be found without knowing its key. -dump renders a page to plain text for a script.
Examples
elinks https://alpinelinux.orgbrowse
elinks gopher://gopher.floodgap.comGopher, in the same browser
elinks -dump https://example.comthe page as text, to stdout
elinks -dump -dump-width 72 URLat a fixed width
g (in the browser) go to a URL
t open a new tab; < > move between tabs
/ search the page
Esc the menu bar; q quit
Options
-dump- render the page as text and print it
-dump-width N- the width -dump lays out to
-source- print the HTML as it arrives
-anonymous- restricted: no local files, no downloads
-no-connect- run without connecting to a running ELinks
Notes
- No JavaScript: a page that builds itself in script is blank. So are most modern sign-in pages.
- Settings are in the menu (Setup) and saved to
~/.config/elinks: change them there rather than editing the file by hand. - A second
elinks joins the first one's session by default; -no-connect keeps them apart.
See also links, lynx, w3m, bombadillo
lftp A file-transfer shell for FTP, SFTP and HTTP: mirror folders, resume, queue.
Internet · terminal program · lftp 4.9.3 · stage 12 · The application catalogue · man lftp(1) · home
needs libcrypto3, libncursesw, readline, libssl3, zlib
On Copal: The catalogue's terminal FTP client. It speaks SFTP over ssh too, and mirrors a whole folder in either direction -- the tool for a web host or an old server that offers only FTP.
Use
Connect, then work with ls, cd, get and put as in a shell. The command to know is mirror: it copies a whole directory tree down, or up with -R, sending only what changed.
Examples
lftp sftp://you@example.orgconnect over SFTP
lftp ftp://ftp.example.organonymous FTP
lftp -u you ftp.example.orgFTP with a password prompt
lftp -c 'open sftp://you@host; mirror site/ ~/site'one command, then quit
mirror REMOTE LOCAL (in lftp) download a tree
mirror -R LOCAL REMOTE upload one
pget -n 4 big.iso a file in four parallel pieces
get -c file resume a download
jobs / bye running transfers / quit
Options
-u USER[,PASS]- log in as USER
-p PORT- the port
-c COMMANDS- run these and exit
-f FILE- run a script of commands
-e COMMANDS- run these, then stay
Notes
- Plain
ftp:// sends the password in the clear. Use sftp:// wherever the server has ssh. mirror without --delete only adds and updates; with it, it removes what the source lacks. Try mirror --dry-run first.- Settings go in
~/.config/lftp/rc (or ~/.lftp/rc if that exists), bookmarks with bookmark add NAME.
See also rsync, curl, ssh
links A text web browser: tables and frames laid out, menus on F9.
Internet · terminal program · links 2.30 · stage 12 · The application catalogue · man links(1) · home
needs libbz2, libcrypto3, libevent, libssl3, zlib, zstd-libs
On Copal: Browsing that works over SSH and on a console with no desktop, in a few hundred kilobytes; the catalogue's Internet section carries it beside lynx, w3m and elinks.
links [options] URL
Use
Read a page in the terminal. Links lays out tables and frames the way a graphical browser would, which makes it the text browser for pages built with them; -dump turns a page into plain text for a script.
Examples
links https://alpinelinux.orgbrowse
links -dump https://example.comthe page as text, to stdout
links -dump -width 72 URL > page.txt # at a fixed width, into a file
links -source URLthe HTML, unrendered
Options
-dump URL- render the page as text and print it
-source URL- print the HTML as it arrives
-width N- the width -dump lays out to
-anonymous- restricted mode: no downloads, no local files
g- (in the browser) go to a URL
/- search the page
d- download the link under the cursor
Esc or F9- the menu; q quits
Notes
- Alpine builds links without graphics, so
-g answers "Graphics not enabled when compiling": this is the text browser only. - No JavaScript. A page that builds itself in script is blank here; try
w3m for the same limit with better forms, or a graphical browser. - No Gopher: for gopher:// use
lynx or elinks.
See also lynx, w3m, elinks, curl
lynx The oldest text web browser still maintained: web and Gopher, keyboard only.
Internet · terminal program · lynx 2.9.3 · stage 12 · The application catalogue · man lynx(1) · home
needs libbz2, libcrypto3, libintl, libncursesw, libssl3, zlib
On Copal: One of the catalogue's text browsers, kept at every level for use over SSH or on a console. It reads Gopher as well as the web, and its -dump is the classic way to turn a page into text.
lynx [options] [optional paths or URLs]
lynx [options] [path or URL] -get_data
data
--
lynx [options] [path or URL] -post_data
data
--
Use “lynx -help” to display a complete list of current options.
Use
Arrows move between links: down and up to the next link, right to follow it, left to go back. It shows a page as a line of text at a time, with no columns or tables laid out, which makes it the most readable of the text browsers with a screen reader.
Examples
lynx https://lite.duckduckgo.combrowse
lynx gopher://gopher.floodgap.comGopher
lynx -dump https://example.comthe page as text, links numbered at the end
lynx -dump -listonly URLonly the list of links
lynx -source URL > page.htmlthe HTML
g (in the browser) go to a URL
/ search the page
o options; q quit
Options
-dump- print the rendered page and quit
-listonly- with -dump: the links only
-nolist- with -dump: no link list at the end
-source- print the HTML
-width N- the width -dump lays out to
-accept_all_cookies- no questions about each cookie
Notes
- It asks about every cookie.
-accept_all_cookies, or set it in o (options) and save. - No JavaScript and no CSS: the page is the page's text, in order. For a site built for phones, that is often the best way to read it.
See also links, elinks, w3m, curl
retawq A tiny multi-window text web browser, with a split screen.
Internet · terminal program · retawq 0.2.6c · stage 12 · The application catalogue · man retawq(1) · home
needs libcrypto3, libncursesw, libssl3
On Copal: The smallest of the catalogue's text browsers, kept at every level: it keeps several pages open at once and shows two side by side, which the others do not.
Use
Open a page, then more windows with n, and split the screen with 2 to read two at once. Most commands are one key; Escape cancels any of them.
Examples
retawq https://example.combrowse
retawq URL1 URL2two documents at once
retawq --dump=https://example.comthe page as text, to stdout
retawq --download=URL > filefetch a file, no display
g (in the browser) go to a URL
n C a new window / close this one
2 1 split the screen / un-split it; Tab between halves
b u bookmarks / the history of URLs
Q quit
Options
--dump=URL- render the page, write it to stdout, quit
--download=URL- write the content of URL to stdout, quit
--colors=off- no colours
--console- console mode: line by line, no full screen
Notes
- It is from 2006 and speaks older HTML well and newer HTML less so; a modern site may come out as a column of text in the wrong order.
- The full key list is in
/usr/share/doc/retawq/key.html -- open it in retawq itself.
See also links, lynx, w3m
speedtest-cli Measure the connection's download speed, upload speed and ping, against speedtest.net.
Internet · command-line tool · speedtest-cli 2.1.3 · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · home
needs python3
On Copal: The store's line test: from a Pi with no browser, is the network slow, or is it something else?
usage: speedtest-cli [-h] [--no-download] [--no-upload] [--single] [--bytes]
[--share] [--simple] [--csv]
[--csv-delimiter CSV_DELIMITER] [--csv-header] [--json]
[--list] [--server SERVER] [--exclude EXCLUDE]
Use
Run it; it picks the nearest speedtest.net server, measures latency, then download and upload, and prints the results.
Examples
speedtest-clithe full test, with progress
speedtest-cli --simplethree lines: ping, download, upload
speedtest-cli --list | headservers near you, with their IDs
speedtest-cli --server 12345test against one server
speedtest-cli --json > result.jsonmachine-readable, for a log
Options
--simple- only ping, download and upload
--list- nearby servers and their IDs
--server ID- use this server
--no-upload- skip the upload test
--bytes- show bytes per second instead of bits
--json / --csv- output for scripts
--share- a link to a result image on speedtest.net
Notes
- Over wifi, the result measures the wifi as much as the line: compare with a cable before blaming the provider.
- A test transfers tens of megabytes; on a metered connection, run it sparingly.
See also curl, ip, iw
w3m A text web browser and pager: tables laid out, good forms, and it pages files too.
Internet · terminal program · w3m 0.5.6 · stage 12 · The application catalogue · man w3m(1) · home
needs libcrypto3, gc, libncursesw, libssl3, zlib
On Copal: One of the catalogue's text browsers, kept at every level. It lays out tables and fills forms better than the others, and doubles as a pager: w3m file.html, or HTML piped into it.
w3m [OPTION]... [ file | URL ]...
Use
Browse with the keyboard, or read HTML from a file or a pipe. It keeps several pages open as tabs, and its forms handle searches and sign-ins that the simpler browsers stumble on (as long as they need no JavaScript).
Examples
w3m https://lite.duckduckgo.combrowse
w3m README.htmla local HTML file
curl -s URL | w3m -T text/htmlHTML from a pipe
w3m -dump https://example.comthe page as text
w3m -dump -cols 72 URL > page.txtat a fixed width
U (in the browser) open a URL
Enter follow the link; B back
T a new tab; { } between tabs
/ search; q quit (Q without asking)
Options
-dump- print the rendered page and quit
-cols N- the width for -dump
-T TYPE- the content type of stdin: text/html
-o OPT=VAL- set an option for this run
-M- monochrome
Notes
- Arrow keys move the cursor, not the page:
Space and b page down and up. Links are followed where the cursor is. o is the options page; changes saved there go to ~/.w3m/config.
See also links, elinks, lynx
Languages
cargo Rust's build tool and package manager: new, build, run, test, install.
Languages · command-line tool · cargo 1.96.1 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man cargo(1) · home
needs rust, libcrypto3, libcurl, scudo-malloc, sqlite-libs, libssh2, libssl3, zlib
On Copal: Stage 7 installs Rust on every port, the Zero included, and several checkouts in ~/code are Rust: copal-build compiles them with cargo and links what they make into ~/.local/bin.
cargo [options] command [args]
cargo [options] --version
cargo [options] --list
cargo [options] --help
cargo [options] --explain code
Use
Every Rust project is a directory with a Cargo.toml. cargo run builds and runs it; cargo build --release makes the fast version in target/release. Dependencies named in Cargo.toml are fetched from crates.io and built with it.
Examples
cargo new hello && cd helloa new project, with git
cargo runbuild (debug) and run
cargo build --releaseoptimised, into target/release/
cargo checktype-check only: much faster than a build
cargo testrun the tests
cargo clippylints: common mistakes, better idioms
cargo fmtformat the code
cargo install ripgrepbuild a tool into ~/.cargo/bin (on PATH)
Options
new NAME- a new project (--lib for a library)
build / run- compile / compile and run; --release for optimised
check- check without producing a binary
test- build and run the tests
clippy / fmt- lint / format
add CRATE- add a dependency to Cargo.toml
install CRATE- build and install a program
-j N- parallel jobs
--offline- use only what is already downloaded
Notes
- This is Alpine's Rust, a release or two behind. A crate that says "requires rustc 1.NN or newer" wants rustup -- and once rustup is in,
~/.cargo/bin comes first on PATH and its cargo replaces this one. which cargo says which you are running. - rustc is an LLVM compiler and hungry: a release build with dependencies can want more than 512 MB. On a Zero it works because of zram, slowly;
-j1 keeps it from running out. cargo build without --release makes a debug build that can run ten times slower. Measure the release one.
See also gdb, git, make, copal-build
clang The LLVM C and C++ compiler: gcc's rival, with clearer errors.
Languages · command-line tool · clang22 22.1.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man clang(1) · home
needs clang22-headers, clang22-libs, fortify-headers, libgcc-static, libstdc++-dev, llvm22-linker-tools, musl-dev, llvm22-libs
On Copal: Stage 7's second compiler, and it brings clangd -- the language server that gives Neovim go-to-definition, references and the call hierarchy in C and C++.
Use
Compile C (clang) or C++ (clang++) with the same flags as gcc. Worth running a program through both: each warns about things the other misses, and clang's messages point at the exact column.
Examples
clang -Wall -Wextra -g hello.c -o hellocompile, like gcc
clang++ -std=c++20 main.cpp -o mainC++
clang -fsyntax-only -Wall file.ccheck, produce nothing
CC=clang makea Makefile's build, with clang
clang --versionwhich LLVM
clang-format -i file.creformat in place
Options
-o FILE- name the output
-g- debug information
-O2- optimise
-Wall -Wextra- warnings
-Weverything- every warning clang has (noisy, but thorough)
-std=c17- the language standard, as gcc
-fsyntax-only- parse and check, write nothing
Notes
clangd needs to know the flags: a compile_commands.json at the project root. bear -- make records one from a Makefile build, and cmake writes one with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON.- Sanitizers: as with gcc, the ASan and UBSan runtimes are missing;
-fsanitize=undefined -fsanitize-trap=undefined needs none, and stops the program at the first undefined behaviour. - Clang links with the system's gcc toolchain and musl, so its programs and gcc's mix freely.
See also gcc, make, cmake, nvim, gdb
clangd The C and C++ language server: completion, go-to-definition, errors as you type.
Languages · command-line tool · clang22-extra-tools 22.1.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs clang22, llvm22-libs, clang22-libs
On Copal: Stage 7 installs it with clang-format (clang22-extra-tools), and Neovim, Helix and Geany talk to it: it is what makes gd, gr and K work in C and C++.
USAGE: clangd [options]
OPTIONS:
Use
You rarely run it yourself: the editor starts it. What it needs from you is the project's build flags, in a compile_commands.json at the root of the project; without one it guesses, and gets includes wrong.
Examples
bear -- makerecord compile_commands.json from a make build
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ONor have cmake write it
ln -s build/compile_commands.json .where clangd looks for it
clangd --check=src/main.ctry it on one file, from the shell
clang-format -i src/*.cits companion: reformat in place
Options
--check=FILE- parse FILE and report what clangd sees
--compile-commands-dir=DIR- where compile_commands.json is
--background-index- index the whole project in the background
--log=verbose- more detail in the editor's log
Notes
- A
.clangd file in the project sets flags without a build system: CompileFlags: { Add: [-std=c17, -Iinclude] }. - In Neovim,
:Lsp says whether it is running for the current file.
See also clang, nvim, hx, bear
composer PHP's dependency manager: fetch the libraries a project needs, and autoload them.
Languages · command-line tool · composer 2.10.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs php85, php85-phar, php85-curl, php85-iconv, php85-mbstring, php85-openssl, php85-zip, p7zip
On Copal: Part of the catalogue's PHP 8.3 row, with Xdebug: for writing PHP programs and trying frameworks on the Pi. The row installs PHP for development, not as a public server.
Usage:
list [options] [--] [<namespace>]
Arguments:
Use
In a project, composer require adds a library and installs it into vendor/; composer install installs exactly what composer.lock records. Your code includes vendor/autoload.php once.
Examples
composer inita composer.json for this folder
composer require monolog/monologadd a library
composer installinstall what composer.lock says
composer updatemove to newer allowed versions
composer create-project laravel/laravel appa new project from a package
Options
init- create composer.json
require PKG- add and install a package
install- install from composer.lock
update- update within composer.json's limits
dump-autoload- regenerate the autoloader
create-project P- start a project from package P
Notes
- Commit
composer.lock: it is what makes install give everyone the same versions. - PHP modules a library needs (
php83-mbstring, php83-pdo...) are apk packages; composer check-platform-reqs names the missing ones.
See also php83
crystal Crystal: Ruby-like syntax, static types inferred, compiled to fast native code.
Languages · command-line tool · crystal 1.20.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man crystal(1) · home
needs gc-dev, gcc, gmp-dev, libatomic_ops, musl-dev, pcre2-dev, llvm22-libs, libffi
On Copal: The catalogue's Crystal, on the 64-bit boards: for people who like writing Ruby and want a compiled, typed program at the end.
crystal command [switches] programfile — [arguments]
Use
crystal run compiles and runs a file; crystal build --release makes an optimised program. crystal init app NAME starts a project with its shard.yml.
Examples
crystal run hello.crcompile and run
crystal hello.crthe same: run is the default
crystal build --release hello.cran optimised program, ./hello
crystal eval 'puts 6 * 7'one line
crystal init app myappa new project
Options
run FILE- build and run (the default)
build FILE- build an executable; --release to optimise
eval CODE- evaluate CODE
init app NAME- start a project
spec- run the tests in spec/
Notes
- shards, its dependency manager, is not installed here.
- A release build of anything sizeable is slow and memory-hungry on a Pi; develop without
--release, release at the end. - 64-bit only: its catalogue row is gated to aarch64 and x86_64.
See also ruby, nim, go
csi CHICKEN Scheme's interpreter -- and csc, which compiles Scheme to C and to programs.
Languages · terminal program · chicken 5.4.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man csi(1) · home
needs gcc, libc-dev, chicken-dev, chicken-libs
On Copal: The catalogue's compiling Scheme: try code in csi, then turn it into a small native program with csc, through C.
csi [OPTION ...] [FILENAME ...]
Use
csi is the interactive interpreter and runs scripts; csc compiles a file to an executable. Libraries ("eggs") install with chicken-install.
Examples
csithe REPL; ,q to leave
csi -s script.scmrun a file as a script
csi -e '(print (* 6 7))'one expression
csc hello.scmcompile to ./hello
chicken-install -s srfi-1an egg, system-wide (as root)
Options
-s FILE- run FILE as a script, then exit
-e EXPR- evaluate EXPR and exit
-q- no banner
-n- do not load ~/.csirc
Notes
- The command names are CHICKEN's own:
csi interprets, csc compiles; there is no chicken command to run. csc needs a C compiler; stage 7's gcc is it.
See also guile, racket, gcc
dlv Delve: the debugger for Go -- breakpoints, stepping, goroutines.
Languages · command-line tool · delve 1.26.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
On Copal: The catalogue's Go debugger. gdb can step through Go but does not understand goroutines, interfaces or Go's types; Delve does.
Usage:
dlv [command]
Available Commands:
Use
dlv debug builds the package in the current folder with debugging on and stops before main. Set breakpoints, continue, and look around at the (dlv) prompt.
Examples
dlv debugbuild and debug the package here
dlv debug -- -v input.txtwith arguments for the program
dlv testdebug the package's tests
dlv exec ./servera binary built already
doas dlv attach $(pidof server)a running process
break main.main (at the prompt) a breakpoint; b file.go:42 for a line
continue run to it (c)
next / step over / into
print x a value (p)
goroutines every goroutine; exit leave
Options
debug [PKG]- build and debug
test [PKG]- debug the tests
exec BINARY- debug a built binary
attach PID- attach to a running process
core BIN CORE- examine a core dump
Notes
- 64-bit only: its catalogue row is gated to aarch64 and x86_64.
- Build with optimisations off to follow the source line by line:
dlv debug does this for you; for exec, build with go build -gcflags=all="-N -l".
See also go, gdb
dotnet The .NET 9 SDK: create, build and run C#, F# and VB programs.
Languages · command-line tool · dotnet-host 10.0.12 · stage 12 · The application catalogue · home
On Copal: The catalogue's .NET, wherever Microsoft builds it -- not on ARMv6 or 32-bit x86. C# console programs and web services run on a Pi.
Usage: dotnet [runtime-options] [path-to-application] [arguments]
Execute a .NET application.
Use
dotnet new makes a project from a template, dotnet run builds and runs it, dotnet publish makes a folder to copy to another machine.
Examples
dotnet new console -o hello && cd helloa new C# console program
dotnet runbuild and run it
dotnet add package Newtonsoft.Jsona NuGet package
dotnet publish -c Release -o outa release build into out/
dotnet new listthe templates there are
Options
new TEMPLATE- create a project (console, classlib, web, ...)
run- build and run the project here
build- build it
add package P- add a NuGet package
publish- produce a deployable folder
test- run its tests
Notes
- It sends usage statistics to Microsoft unless
DOTNET_CLI_TELEMETRY_OPTOUT=1 is set; put the export in ~/.profile.local to keep it. - The first
dotnet new or run is slow while it sets up; later ones are quicker.
See also pwsh, java
elixir Elixir: a friendly functional language on the Erlang VM, built for concurrency.
Languages · terminal program · elixir 1.19.6 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man elixir(1) · home
needs erlang, erlang-dev
On Copal: The catalogue's Elixir, with iex for trying things and mix for projects: millions of lightweight processes, on a Pi.
elixir [OPTIONS] file ...
Use
iex is the interactive shell. elixir runs a script (.exs). mix creates, builds, tests and runs projects.
Examples
iexthe interactive shell; Ctrl-C twice to leave
elixir script.exsrun a script
elixir -e 'IO.puts 6 * 7'one expression
mix new hello && cd helloa new project
mix testits tests; mix run to run it
Options
-e CODE- evaluate CODE
-r FILE- require FILE first
--no-halt- keep the VM running after the script
-v, --version- the Elixir and Erlang versions
Notes
mix deps.get fetches dependencies from hex.pm; the first time it asks to install Hex itself -- answer yes.- It is Erlang underneath:
erl is also here, and Erlang libraries work from Elixir.
See also ruby, erlang
fpc Free Pascal: a compiler for Pascal and Object Pascal, Turbo Pascal and Delphi dialects included.
Languages · command-line tool · fpc 3.2.2 · stage 12 · The application catalogue · man fpc(1) · home
On Copal: The catalogue's Pascal: old Turbo Pascal programs and new Object Pascal ones compile here, quickly, into small native programs.
fpc [options] [sourcefile]
Use
Give it a .pas file; it writes a program named after it. A mode switch chooses the dialect when compiling older code.
Examples
fpc hello.pascompile; run with ./hello
fpc -O2 prog.pasoptimised
fpc -Mtp old.pasin Turbo Pascal mode
fpc -Mdelphi unit.pasin Delphi mode
fpc -g prog.paswith debug information
Options
-o<NAME>- the output name (no space: -ohello)
-O1 / -O2- optimisation levels
-g- debug information
-M<MODE>- dialect: fpc, objfpc, tp, delphi
-Fu<DIR>- where to find units
-h- every option
Notes
- Options take their value with no space:
-ohello, -Fu./units. - It comes from Alpine's testing repository (
fpc@testing).
See also gcc
gfortran The GNU Fortran compiler: FORTRAN 77 through Fortran 2018.
Languages · command-line tool · gfortran 15.2.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man gfortran(1) · home
needs gcc, libgfortran, gmp, isl25, mpc1, mpfr4, zlib
On Copal: Stage 7's Fortran, for numerical code old and new -- and the compiler R and SciPy-style builds need for their Fortran parts.
gfortran [-c|-S|-E]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-pedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...]
[-mmachine-option...]
[-o outfile] infile...
Only the most useful options are listed here; see below for the remainder.
Use
Compile .f90 (free form) or .f (fixed form, FORTRAN 77) files as gcc compiles C. The standard is chosen with -std.
Examples
gfortran -Wall -g hello.f90 -o hellocompile, warnings on
gfortran -O2 -std=f2018 model.f90 -o modeloptimised, Fortran 2018
gfortran -std=legacy old.f -o olda FORTRAN 77 program
gfortran -c util.f90 && gfortran main.f90 util.o -o progmodules, then link
gfortran -fcheck=all -g prog.f90run-time bounds checking
Options
-o FILE- the output
-g- debug information
-Wall- warnings
-std=STD- legacy, f95, f2003, f2008, f2018
-fcheck=all- check array bounds and more at run time
-ffree-form / -ffixed-form- override what the extension says
Notes
- A module's
.mod file is written where it is compiled: compile the modules before the programs that use them. - Optimisation levels (
-O2, -O3) are gcc's, shared by every language it compiles: man gcc documents them. -fcheck=all finds the out-of-bounds errors that are silent otherwise; keep it for debugging, it slows the program.
See also gcc, gdb, make
ghc The Glasgow Haskell Compiler, with ghci for trying things and cabal for projects.
Languages · command-line tool · ghc 9.10.3 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs gmp-dev, libffi-dev, perl, gcc, llvm15, clang16, libffi, gmp
On Copal: The catalogue's Haskell, on the 64-bit Pis and PCs. GHC is not built for 32-bit ARM at all -- it bootstraps from an earlier GHC -- so on a Zero the nearest in spirit is OCaml.
Usage:
ghc-9.10.3 [command-line-options-and-input-files]
Use
ghci is the interactive prompt, where most learning happens. ghc compiles a file to a program. cabal makes, builds and runs projects with their dependencies.
Examples
ghcithe prompt: :t for a type, :q to leave
runghc Main.hsrun a file without compiling it
ghc -O2 Main.hs -o maincompile a program
cabal initstart a project here
cabal update && cabal runfetch the package list, build and run
Options
-o FILE- the output
-O- optimise (-O2 for more)
-Wall- warnings
--make- build a program and its modules (the default)
-i DIR- search DIR for modules
Notes
cabal update is needed once before any package can be installed.- A first
cabal build of a project with dependencies compiles them all: on a Pi, that is a long wait and a lot of memory -- zram helps.
See also hlint, ocaml
go The Go toolchain: build, run, test and fetch Go programs.
Languages · command-line tool · go 1.26.8 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man go(1) · home
needs binutils, gcc, musl-dev
On Copal: Stage 7 installs Go on every port, with gopls for Neovim. Several of the terminal programs Copal ships are Go, and Go is the easiest way to build one program for every Pi from one machine.
go command [arguments]
Use
A Go project is a module: a directory with go.mod. go run . builds and runs it, go build leaves a single static binary, and go install builds a program from the internet into ~/go/bin.
Examples
go mod init example.com/hellostart a module here
go run .build and run it
go build -o hello .a binary called hello
go test ./...every package's tests
go install github.com/charmbracelet/glow@latesta tool, into ~/go/bin
GOOS=linux GOARCH=arm GOARM=6 go build -o hello-zero .for a Pi Zero
go env GOPATHwhere downloads and installs go
Options
run .- build and run the package here
build -o FILE- compile to FILE
test ./...- run tests, recursively
install PKG@VER- build and install a program
mod init PATH- start a module
mod tidy- add missing and remove unused dependencies
fmt ./...- format the code (gofmt)
vet ./...- report suspicious code
env- the toolchain's settings; GOOS, GOARCH, GOARM, CGO_ENABLED
Notes
- Cross-compiling is the trick: set
GOOS, GOARCH (arm64, arm, amd64) and for 32-bit ARM GOARM (6 for a Zero, 7 for a Pi 2), and the binary runs there -- as long as CGO_ENABLED=0 or no C is involved. ~/go/bin is on PATH on a Copal machine; Alpine alone does not put it there.- A program that uses C through cgo needs gcc and links against musl; such a binary will not run on a glibc system.
See also gdb, dlv, git, cargo
guile GNU Guile: a Scheme for scripting, extending programs, and learning Lisp.
Languages · terminal program · guile 3.0.9 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man guile(1) · home
needs guile-libs
On Copal: The catalogue's Scheme from the GNU project -- the extension language of GNU programs, and a good first Lisp with a helpful REPL.
guile [-L DIRECTORY] [-l FILE] [-e FUNCTION] [\] [-c EXPR] [-s SCRIPT] [--] [SCRIPT
[ARGs for SCRIPT]]
Only the most useful options are listed here; see below for the remainder.
Use
Start the REPL and type expressions, or run a file of Scheme. Commands to the REPL itself start with a comma.
Examples
guilethe REPL; ,q to leave
guile script.scmrun a file
guile -c '(display (* 6 7)) (newline)'one expression
guile -L . -l lib.scmload a file, with this folder on the path
(define (square x) (* x x)) (at the REPL) define
(map square '(1 2 3)) => (1 4 9)
,help the REPL's own commands
Options
-c EXPR- evaluate EXPR and exit
-l FILE- load FILE
-L DIR- add DIR to the module search path
-s FILE- run FILE as a script
--no-auto-compile- do not cache compiled files
Notes
- The first run of a file compiles it and caches the result under
~/.cache/guile; later runs start faster. guile-readline gives the REPL history and line editing: (use-modules (ice-9 readline)) (activate-readline) in ~/.guile.
See also csi, racket, sbcl
hlint Suggest better Haskell: simpler expressions, library functions you missed.
Languages · command-line tool · hlint 3.10 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs libffi, gmp
On Copal: The catalogue's Haskell linter, the usual companion to GHC: it teaches idiomatic Haskell as it points things out.
Use
Run it on a file or a folder; it prints each suggestion with the code as it is and as it could be.
Examples
hlint Main.hssuggestions for one file
hlint src/a whole folder
hlint --report src/an HTML report, report.html
Options
--report- write an HTML report
--hint=FILE- use hints from FILE
-j- use several cores
Notes
- A suggestion can be switched off for a project in
.hlint.yaml: - ignore: {name: "Use camelCase"}. - 64-bit only, like GHC.
See also ghc
java OpenJDK 21: run Java programs, and with javac and jshell, write them.
Languages · command-line tool · openjdk21-jre-headless 21.0.12_p8 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs java-common, java-cacerts, zlib
On Copal: The catalogue's Java, on the 64-bit boards: for the programs that ship as a .jar, and for learning or writing Java itself.
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
Use
java File.java compiles and runs a single-file program at once. javac compiles, java -jar runs a packaged program, and jshell is an interactive prompt.
Examples
java Hello.javacompile and run one file
javac Hello.java && java Hellocompile, then run the class
java -jar program.jara packaged program
jshelltry Java a line at a time; /exit leaves
java -Xmx256m -jar program.jarcap its memory on a small board
Options
-jar FILE- run a packaged program
-cp PATH- where to find classes and jars
-Xmx SIZE- the most heap it may use: -Xmx256m
-version- the version (to stderr)
Notes
- On a Pi with little memory,
-Xmx keeps a program from taking all of it; Java's default is a quarter of RAM. - 64-bit only: its catalogue row is gated to aarch64 and x86_64.
See also plantuml
lua5.4 The Lua 5.4 interpreter -- with LuaJIT beside it for speed.
Languages · terminal program · lua5.4 5.4.8 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man lua5.4(1) · home
needs lua5.4-libs, readline
On Copal: The catalogue's Lua: the small language Neovim, many games and configuration files are scripted in. The command carries its version; luajit is the fast 5.1-compatible one.
lua [ options ] [ script [ args ] ]
Use
Run a script, or start the prompt and type. -e runs a line.
Examples
lua5.4the prompt; Ctrl-D leaves
lua5.4 script.luarun a script
lua5.4 -e 'print(2^10)'one line
luajit script.luathe same script, often much faster
lua5.4 -i config.luarun it, then stay at the prompt
Options
-e CODE- run CODE
-i- stay interactive after running a script
-l NAME- require library NAME first
-v- the version
Notes
- Plain
lua may be another version: on a machine where something pulled in Lua 5.1, lua is 5.1. Say lua5.4 to be sure; lua -v tells. - LuaJIT implements Lua 5.1, not 5.4: integer division
// and some newer features are missing there. - Libraries come from Alpine as
lua5.4-* packages.
See also nvim, lua-language-server
nim Nim: a compiled language that reads like Python and runs like C.
Languages · command-line tool · nim 2.2.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs libucontext-dev
On Copal: The catalogue's Nim: small, fast programs from code as terse as a script, on every port the Pi runs.
Use
nim c compiles a file through C; -r runs the result. -d:release turns on the optimisations for the version you keep.
Examples
nim c -r hello.nimcompile and run
nim c -d:release -o:hello hello.niman optimised program called hello
nim r hello.nimcompile and run, no binary kept
nim check hello.nimcheck it without building
Options
c / compile- compile to C, then to a program
r- compile and run, leaving no binary behind
-r, --run- run after compiling
-d:release- optimised build
-o:FILE- the output name
check- check the file for errors only
Notes
- nimble, Nim's package manager, is not installed here; a few libraries come from Alpine as
nim-* packages. - The build cache is
~/.cache/nim; delete it if builds behave oddly.
See also python3, gcc, crystal
ocaml OCaml: a strict functional language with ML's type inference, and a fast native compiler.
Languages · terminal program · ocaml 4.14.4 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ocaml(1) · home
needs ocaml-runtime, gcc
On Copal: The catalogue's ML on every port, the Zero included: where GHC is not built, OCaml gives the same type system, pattern matching and inference, with a native compiler small enough for the board.
ocaml [ options ] [ object-files ] [ script-file ]
Use
ocaml is the interactive toplevel: type an expression, end it with ;;. ocamlopt compiles to a native program, ocamlc to bytecode.
Examples
ocamlthe toplevel; #quit;; to leave
ocaml script.mlrun a file
ocamlopt -o hello hello.mla native executable
ocamlc -o hello.byte hello.mlbytecode, runs anywhere OCaml does
let square x = x * x;; (at the toplevel) define
List.map square [1; 2; 3];; use: - : int list = [1; 4; 9]
Options
FILE- run it
-I DIR- search DIR for compiled modules
-init FILE- load FILE at start instead of ~/.ocamlinit
Notes
- This is OCaml 4.14. opam and dune are not installed; libraries come from Alpine as
ocaml-* packages (apk search ocaml-). - Every toplevel input ends with
;;, or nothing happens.
See also ghc, racket
perl Perl: text processing, one-liners, and a great deal of Unix glue.
Languages · command-line tool · perl 5.42.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man perl(1) · home
needs libbz2, zlib
On Copal: On every Copal machine: much of the system's own tooling is Perl, and its one-liners edit files and reports faster than anything.
perl [ -sTtuUWX ]
[ -hv ] [ -V[:configvar] ]
[ -cw ] [ -d[t][:debugger] ] [ -D[number/list] ]
[ -pna ] [ -Fpattern ] [ -l[octal] ] [ -0[octal/hexadecimal] ]
[ -Idir ] [ -m[-]module ] [ -M[-]'module...' ] [ -f ]
[ -C [number/list] ]
[ -S ]
[ -x[dir] ]
[ -i[extension] ]
[ [-e|-E] 'command' ] [ -- ] [ programfile ] [ argument ]...
For more information on these options, you can run "perldoc perlrun".
Use
Run a script, or a one-liner with -e. With -n or -p it loops over every input line; with -i it edits files in place.
Examples
perl -e 'print 2**40, "\n"'one line
perl -ne 'print if /error/i' log.txtgrep, case-insensitive
perl -pi -e 's/colour/color/g' *.mdedit files in place
perl -pi.bak -e 's/foo/bar/' confthe same, keeping conf.bak
perldoc -f sprintfthe manual for one function
Options
-e CODE- run CODE
-n / -p- loop over input lines (-p also prints each)
-i[EXT]- edit in place, keeping a backup with EXT
-l- chomp input lines and add newlines to print
-w- warnings
-M MODULE- use MODULE first
Notes
- Libraries come from Alpine as
perl-* packages: apk search perl-json. cpan is not installed. -i without an extension edits with no backup; give one while learning.
See also awk, sed, python3, ruby
racket Racket: a Scheme descendant built for making languages -- and for teaching.
Languages · terminal program · racket 9.2 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man racket(1) · home
needs ca-certificates, libcrypto3, libssl3, lz4-libs, libncursesw, zlib
On Copal: The catalogue's Racket, with raco for packages and builds. How to Design Programs is taught in it, and its #lang line makes a file any of many languages.
racket [ option ... ] [ argument ... ]
Use
Run a .rkt file, or start the REPL. The first line of a file, #lang racket, says which language it is written in.
Examples
racketthe REPL; ,exit to leave
racket hello.rktrun a file
racket -e '(displayln (* 6 7))'one expression
raco make hello.rktcompile it ahead of time
raco pkg install gregora package
Options
-e EXPR- evaluate EXPR
-i- the REPL, after the other options
-l LIB- require LIB first
-t FILE- require FILE (runs it)
Notes
- DrRacket, the teaching IDE, is a separate window program; this is the command line.
- Packages install per user under
~/.local/share/racket.
See also guile, csi, sbcl
retro RetroForth: a small, modern language in the Forth family.
Languages · terminal program · retroforth 2025.08 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man retro(1) · home
On Copal: The catalogue's Forth. Alpine packages no gforth on any architecture; RetroForth is packaged everywhere and actively kept. It is not ANS Forth: the words differ.
retro [-h] [-i] [-v] [-t filename] [-f filename] [-p filename] [-u filename] [-r filename]
[filename script-args]
Use
Type at the prompt, or run a file. Values go on a stack; words take them off and put results back. A prefix says what a token is: # a number, ' a string, : a new definition.
Examples
retrothe interactive prompt
retro program.retrorun a file
echo "#2 #3 + n:put" | retroprints 5
2 #3 + n:put (at the prompt) add, print the number
'hello s:put print a string
:square dup * ; define a word
7 square n:put use it: 49
Options
-i- interactive mode
-f FILE- run the code blocks in FILE
-h- the usage
Notes
- Code in a
.retro file runs only inside fenced blocks (~~~ lines): the rest is prose, literate-programming style. copal-guide languages says more about why it is Retro, not gforth.
See also guile, lua5.4
ruby The Ruby language: scripts, one-liners, and gems.
Languages · terminal program · ruby 3.4.9 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man ruby(1) · home
needs ca-certificates, gmp, ruby-libs, libucontext, zlib
On Copal: The catalogue's Ruby, with irb for trying things and gem for libraries -- for scripting, and for the tools written in it.
ruby [--copyright] [--version] [-SUacdlnpswvy] [-0[octal]] [-C directory] [-E
external[:internal]] [-F[pattern]] [-I directory] [-K[c]] [-T[level]] [-W[level]] [-e
command] [-i[extension]] [-r library] [-x[directory]] [--{enable|disable}-FEATURE]
[--dump=target] [--verbose] [--crash-report=template] [--] [program_file] [argument ...]
Use
Run a script, or irb to type Ruby interactively. -e runs one line; with -n or -p it runs over every line of input, like awk.
Examples
irbinteractive Ruby; exit to leave
ruby script.rbrun a script
ruby -e 'puts 2**100'one line
ruby -ne 'puts $_ if /error/' log.txtgrep, in Ruby
gem install --user-install rakea gem, in your home
Options
-e CODE- run CODE
-n / -p- loop over input lines (-p also prints them)
-i[EXT]- edit files in place (with -p)
-I DIR- add DIR to the load path
-w- warnings
Notes
gem install without --user-install wants to write system directories: use --user-install, or an apk add ruby-NAME package.- User gems' commands land in
~/.local/share/gem/ruby/*/bin, which is not on PATH until you add it.
See also python3, perl, crystal
rust-analyzer The Rust language server: completion, types on hover, go-to-definition, inline errors.
Languages · command-line tool · rust-analyzer 2026.06.08 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs rust-src, mimalloc2
On Copal: Stage 7 installs it with Rust, and Neovim and Helix start it for .rs files. It is what makes a Rust project navigable in the editor.
Use
The editor runs it; there is nothing to start by hand. Open a file inside a Cargo project and it indexes the project, then answers the editor.
Examples
rust-analyzer --versionwhich version is installed
rust-analyzer diagnostics .the project's errors, from the shell
which rust-analyzerwhich one the editor will find
Options
diagnostics DIR- print the diagnostics for the project in DIR
--version- the version
Notes
- It needs the standard library's source:
rust-src, which the Rust row installs. - With rustup installed,
~/.cargo/bin comes first on PATH and its rust-analyzer is a proxy that says "unavailable for the active toolchain" until rustup component add rust-analyzer. - The first index of a large project takes a while and a lot of memory on a small Pi.
See also cargo, nvim, hx
sbcl Steel Bank Common Lisp: a fast, native Common Lisp compiler with an interactive REPL.
Languages · terminal program · sbcl 2.6.5 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man sbcl(1) · home
needs zstd-libs
On Copal: The catalogue's Common Lisp: it compiles every expression to native code as you type it, so the REPL is as fast as a built program.
Use
Start the REPL and type forms, or run a file with --script. Emacs and Neovim plugins can talk to it for a full Lisp environment.
Examples
sbclthe REPL; (quit) to leave
sbcl --script hello.lisprun a file and exit
sbcl --eval '(print (expt 2 100))' --quitone expression
sbcl --load project.lispload a file, then the REPL
(defun square (x) (* x x)) (at the REPL) define
(square 12) => 144
Options
--script FILE- run FILE non-interactively, then exit
--load FILE- load FILE, then continue
--eval FORM- evaluate FORM
--quit- exit after the --load and --eval options
--noinform- no banner
Notes
- An error drops into the debugger, with numbered restarts: type the number of
ABORT (usually 0) to get back to the prompt. - Libraries come through Quicklisp, which is installed by loading its
quicklisp.lisp from quicklisp.org once.
See also guile, racket, csi
tcc The Tiny C Compiler: compiles C almost instantly, and can run a C file as a script.
Languages · command-line tool · tcc 0.9.27_git20250619 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · man tcc(1) · home
needs tcc-libs
On Copal: The catalogue's fastest C compiler: for trying an idea, or running C like a script, on a board where gcc takes its time.
usage: tcc [options] [infile1 infile2...] [-run infile args...]
Use
Compile as with gcc, or tcc -run file.c to compile and run in one go, in memory. It optimises little: for speed of compiling, not of the program.
Examples
tcc -run hello.ccompile and run, no file left behind
tcc -run prog.c arg1 arg2with arguments for the program
tcc -o hello hello.can executable
echo 'int main(){return 42;}' | tcc -run -from stdin
Options
-run- compile and run at once
-o FILE- the output
-c- compile to an object file
-g- debug information
-Wall- warnings
-I DIR- a header directory; -L DIR -lNAME libraries
Notes
- A file starting
#!/usr/bin/tcc -run can be made executable and run directly, like a shell script. - It supports C99 and most of C11; code leaning on GCC extensions may not compile.
See also gcc, clang
zig The Zig language and toolchain -- and a C compiler that cross-compiles anywhere.
Languages · command-line tool · zig 0.16.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs llvm21-libs, clang21-libs, lld21-libs
On Copal: The catalogue's Zig, on the 64-bit boards. Beside the language, zig cc compiles C for any target from this machine, a Zero or a Mac included.
Usage: zig [command] [options]
Commands:
Use
zig run compiles and runs a file; zig build-exe makes a program; zig init starts a project that zig build builds.
Examples
zig run hello.zigcompile and run
zig build-exe hello.zig -O ReleaseSmalla small, optimised program
zig init && zig build runa new project, built and run
zig test sum.zigrun a file's tests
zig cc -o hello hello.c -target arm-linux-musleabihfC, for a 32-bit Pi
Options
run FILE- compile and run
build-exe FILE- make an executable
init- start a project here
build- build the project (build.zig)
test FILE- run the tests
fmt FILE- reformat the source
cc- act as a C compiler (with -target for another machine)
Notes
- The language is not at 1.0: code written for another Zig version may need changes.
zig version says which this is. - 64-bit only: its catalogue row is gated to aarch64 and x86_64.
See also gcc, clang, go
Mail
aerc A modern terminal mail client: tabs, vim-style keys, and a setup wizard.
Mail · terminal program · aerc 0.21.0 · stage 12 · The application catalogue · man aerc(1) · home
needs less, ncurses, notmuch-libs
On Copal: The catalogue's newest terminal mail client: it walks you through the account on first start, keeps several mailboxes in tabs, and opens the editor in a terminal inside itself.
aerc [-h] [-v] [-a <name>] [-C <file>] [-A <file>] [-B <file>] [-I] [mailto:<...> |
mbox:<file> | :<command...>]
For a guided tutorial, use :help tutorial from aerc, or man aerc-tutorial from your terminal.
Use
Start it; the first time, a wizard asks for your address and servers and writes the account file. After that it is tabs of mailboxes and messages, with the keys and :commands of vim.
Examples
aercstart; the wizard on first run
aerc mailto:you@example.orgcompose to an address
j k Enter (in aerc) move / open a message
C Rr rr compose / reply / reply to all
:new-account run the wizard for another account
Ctrl-N Ctrl-P next / previous tab; q close a message, or quit
Options
-A FILE- another accounts.conf
-C FILE- another aerc.conf
-v- the version
mailto:URL- start composing to that address
Notes
- Accounts are in
~/.config/aerc/accounts.conf, passwords included unless a source-cred-cmd fetches them: keep that file private (chmod 600). - The keys are its
binds.conf; :help keys lists what is bound. - HTML mail shows as text only when a filter is configured; the default filters are in
aerc.conf's [filters] section.
See also mutt, alpine, vim
alpine The pine mail reader, continued: menus on screen, IMAP and SMTP built in.
Mail · terminal program · alpine 2.26 · stage 12 · The application catalogue · man alpine(1) · home
needs libcrypto3, libldap, libncursesw, libssl3
On Copal: The catalogue's gentlest terminal mail client, and the heir to elm, which Alpine no longer packages. Every key it takes is listed at the foot of the screen.
Use
Set up your account once in Setup, then read, write and file mail with the single-letter commands shown at the bottom of every screen. It talks to an IMAP server for reading and an SMTP server for sending, so the mail stays on the server.
Examples
alpinestart; the main menu
alpine you@example.orgstraight to composing a message
alpine -f INBOXopen a folder directly
alpine -istraight to the message index
S C (in alpine) Setup, then Config: server names, your address
I L the message index / the folder list
C R F compose / reply / forward
Ctrl-X send, from the composer; Q quit
Options
ADDRESS- start composing to ADDRESS
-f FOLDER- open FOLDER
-i- start in the index
-I KEYS- type these keys at start (a script of commands)
-p FILE- use FILE as the configuration instead of ~/.pinerc
-d N- debug level
Notes
- Server names go in Setup > Config:
inbox-path as {imap.example.org/ssl/user=you}INBOX, and smtp-server as smtp.example.org/submit/user=you -- the braces and slashes are alpine's own syntax. - The configuration is
~/.pinerc; the Setup screens write it for you. - Gmail and most large providers want an app password, not your normal one, for a program like this.
See also mutt, aerc, mail
mail Send a message from a script, or read local mail, in a line or two.
Mail · command-line tool · mailx 8.1.2_git20220412 · stage 12 · The application catalogue · man mail(1) · home
needs libbsd, liblockfile
On Copal: The catalogue's mail for scripts (mailx), standing in for elm, which Alpine no longer packages. A cron job or a build can mail a result.
mail [-dEIinv] [-a header] [-b bcc-addr] [-c cc-addr] [-r from-addr] [-s subject] [--]
to-addr ...
mail [-dEIiNnv] -f [file]
mail [-dEIiNnv] [-u user]
Use
Pipe a body into mail -s SUBJECT ADDRESS and it is handed to the system's mail transport. Without arguments it reads the local mailbox, /var/mail/$USER, the way system messages are delivered.
Examples
echo 'Build done' | mail -s 'copal' you@example.orgsend one line
mail -s 'Log' you@example.org < build.loga file as the body
mail -c boss@example.org -s 'Report' you@example.org < r.txtwith a copy
mailread local mail
doas apk add msmtpa way out to real servers
Options
-s SUBJECT- the subject
-c ADDRS- carbon copies
-b ADDRS- blind carbon copies
-f FILE- read FILE as the mailbox
-v- show the delivery's conversation
Notes
- On Copal nothing is sent until there is a way out.
mail hands the message to /usr/sbin/sendmail, which is BusyBox's, and it only forwards to an SMTP server it is told about. Install msmtp, give it your server in ~/.config/msmtp/config, and put set sendmail=/usr/bin/msmtp in ~/.mailrc. - This is BSD mail (mailx), not s-nail or Heirloom mailx: the
-S smtp= recipes found online are for those, and do not work here.
See also mutt, alpine
mutt A terminal mail reader configured entirely in text: IMAP, SMTP, and every key rebindable.
Mail · terminal program · mutt 2.3.2 · stage 12 · The application catalogue · man mutt(1) · home
needs libcrypto3, gdbm, libgpg-error, gpgme, libgsasl, libidn2, libintl, libncursesw
On Copal: The catalogue's configurable terminal mail client, built here with IMAP, SMTP and TLS, so one config file makes it a complete client.
mutt [-nRyzZ] [-e command] [-F rcfile] [-m type] [-f mailbox]
mutt [-Enx] [-e command] [-F rcfile] [-H draft] [-i include]
[-b bcc-addr] [-c cc-addr] [-s subject]
[-a file ... --] to-addr ...
mutt [-nx] [-e command] [-F rcfile] [-b bcc-addr] [-c cc-addr]
[-s subject] [-a file ... --] to-addr ... < message
mutt [-n] [-e command] [-F rcfile] -p
mutt [-n] [-e command] [-F rcfile] -A alias
mutt [-n] [-e command] [-F rcfile] -Q variable
...
Use
Write a muttrc with your servers, start it, and read mail from an index of messages. Replies and new messages open in your editor ($EDITOR), and are sent when you leave it and confirm.
Examples
muttthe inbox, from the config
mutt -f imaps://you@imap.example.org/an IMAP mailbox without a config
mutt -s 'Report' you@example.org < report.txtsend from a script
mutt -s 'Photos' -a pic.jpg -- you@example.org < note.txtwith an attachment
mutt -vthe version, and what it was built with
j k Enter (in mutt) move / open a message
m r g compose / reply / reply to all
c change to another mailbox; q quit
Options
-f MAILBOX- open MAILBOX: a path, or imaps://user@host/
-s SUBJECT- the subject, when sending from the command line
-a FILE -- TO- attach FILE (the -- ends the attachments)
-F FILE- use FILE as the muttrc
-n- ignore the system configuration
-v- version and build options
Notes
- The whole configuration is
~/.muttrc (or ~/.config/mutt/muttrc). The minimum: set folder, set spoolfile, set smtp_url and set from, with the servers as imaps:// and smtps:// URLs. - This build has IMAP, SMTP and OpenSSL but not SASL, so exotic sign-in methods are out; a password or app password works.
- Its editor is
$EDITOR -- nvim on a Copal machine with stage 7.
See also aerc, alpine, mail, vim
profanity A terminal XMPP (Jabber) chat client, with OMEMO encryption.
Mail · terminal program · profanity 0.18.1 · stage 12 · The application catalogue · man profanity(1) · home
needs libcurl, libgcrypt, glib, libncursesw, libotr, readline, libsignal-protocol-c, sqlite-libs
On Copal: The catalogue's XMPP client: chat on a federated network from a terminal, end to end encrypted, on any machine -- over SSH too.
profanity [-vh] [-l level] [-a account]
Use
Connect with your XMPP address, then chat with contacts or join rooms. Each conversation is a window, switched with Alt and a number. /help lists every command.
Examples
profanitystart
profanity -a you@example.orgconnect as that account at once
/connect you@example.org (in profanity) sign in
/msg friend@example.org open a chat
/join room@conference.example.org join a room
/omemo gen make this device's encryption keys
/quit leave
Options
-a ACCOUNT- connect with a saved account
-l LEVEL- log level
-v- the version
Notes
/account add NAME saves an account so -a NAME and /connect NAME work; settings go to ~/.config/profanity/profrc.- OMEMO is per device: after
/omemo gen, start it in a chat with /omemo start, and trust the other side's fingerprints when asked.
See also irssi, weechat
weechat A terminal chat client for IRC, with a nick list, mouse support and plugins.
Mail · terminal program · weechat 4.9.2 · stage 12 · The application catalogue · man weechat(1) · home
needs cjson, libcurl, libgcrypt, gnutls, libintl, libncursesw, zlib, zstd-libs
On Copal: The catalogue's other IRC client: more on screen than irssi -- a buffer list, a nick list -- and the same life in tmux on a machine that stays on.
weechat [-a|--no-connect] [-d|--dir <path>] [-t|--temp-dir] [-p|--no-plugin] [-P|--plugins <plugins>] [-r|--run-command <command>] [-s|--no-script] [--upgrade] [debug-option...] [plugin:option...]
weechat [-c|--colors]
weechat [-h|--help]
weechat [-l|--license]
weechat [-v|--version]
Use
Add a server once, connect, join channels. Every channel and private conversation is a buffer; Alt with the arrows, or Alt and a number, moves between them.
Examples
weechatstart
/server add oftc irc.oftc.net/6697 -tls (in weechat) add a network
/connect oftc connect to it
/join #alpine-linux join a channel
/buffer 3 or Alt-3 switch buffer
/set irc.server.oftc.autoconnect on connect at every start
/quit leave
Options
-d DIR- another configuration directory
-r COMMAND- run a command after starting
-a- do not connect automatically this time
-v- the version
Notes
- Settings are saved as they change, in
~/.config/weechat; /save forces it. /fset is the settings browser: search a word and change it in place, instead of hunting through /set.- Passwords belong in
/secure, which encrypts them, not in plain /set values.
See also irssi, tmux, profanity
Network
bluetoothctl Pair, trust and connect Bluetooth devices, from a prompt or one command at a time.
Network · bluez 5.86 · stage 10 · Wireless, audio, capture and disks · man bluetoothctl(1) · home
needs dbus, dbus-libs, glib, json-c, readline, eudev-libs
On Copal: Stage 10 installs BlueZ and starts its service where there is a controller. Keyboards, mice, controllers and headphones all pair here; there is no graphical pairing tool on Copal.
bluetoothctl [-a capability] [-e] [-m] [-t seconds] [-v] [-h]
Use
Run it for an interactive prompt: power on, scan, pair, trust, connect. Pair once and trust once; after that the device reconnects by itself.
Examples
bluetoothctlthe prompt; then:
power on the controller on
agent on answer pairing requests...
default-agent ...from this prompt
scan on wait for the device's address
pair AA:BB:CC:DD:EE:FF pair (accept the PIN if asked)
trust AA:BB:CC:DD:EE:FF let it reconnect by itself
connect AA:BB:CC:DD:EE:FF connect now
bluetoothctl devicesone command, no prompt: known devices
bluetoothctl --timeout 10 scan onscan for ten seconds, then stop
bluetoothctl remove AA:BB:CC:DD:EE:FFforget a device
Options
power on|off- the controller
scan on|off- look for devices
pair / trust / connect ADDR- the three steps
disconnect ADDR- drop the connection
remove ADDR- forget it altogether
devices- the known devices
info ADDR- one device's state: paired, trusted, connected
--timeout SECS- stop a non-interactive command after SECS
Notes
- "No default controller available": no Bluetooth hardware, or the service is not running --
rc-service bluetooth status. The first Pi Zero and most VMs have none. - Headphones pair and connect, but PipeWire plays to them only with its Bluetooth module,
pipewire-spa-bluez. Stage 10 installs it from 24 Sep 2026; on a machine installed before that, doas apk add pipewire-spa-bluez, then log out and in. - A device that pairs but will not connect again after a reboot was not trusted.
trust ADDR.
See also wpctl, rc-service
curl Fetch or send one URL -- HTTP, HTTPS, FTP and more -- from the command line.
Network · curl 8.22.0 · stage 4 · X.Org, i3, a terminal and a browser · man curl(1) · home
needs libcurl, zlib
On Copal: Every download in Copal's install is curl: Mini vMac's sources, the Hyprland configs, the store's release files, each checked against its sha256. It is also how to test a web server or an API.
curl [options / URLs]
Use
Given a URL, print what is there. Save it with -o or -O, follow redirects with -L, and add -f so a server error is an error, not an HTML page saved under your filename.
Examples
curl https://example.comthe page, to the terminal
curl -fLO https://host/file.tar.gzdownload, under the name in the URL
curl -fL -o out.iso -C - URLresume a download that stopped
curl -I https://example.comthe response headers only
curl -fsSL URL | sha remote install script (read it first)
curl -d 'name=copal' https://host/formPOST form data
curl --json '{"a":1}' https://host/apiPOST JSON, with its headers
curl -s -o /dev/null -w '%{http_code}\n' URLjust the status code
Options
-o FILE- save to FILE
-O- save under the URL's own filename
-L- follow redirects
-f, --fail- exit non-zero on an HTTP error, save nothing
-s -S- silent, but still show errors (-sS)
-C -- continue a partial download where it stopped
-I, --head- headers only
-d DATA- POST DATA
--json DATA- POST JSON, with the Content-Type set
-H 'Name: value'- add a header
-u USER:PASS- log in
-w FORMAT- print details after: %{http_code}, %{size_download}
--retry N- try again on a transient failure
Notes
- Without
-L, a download that redirects -- GitHub release files all do -- saves a tiny redirect page. Without -f, a 404 saves the error page. -fL is the habit. - Without
-o or -O, a binary goes to the terminal; curl refuses and says so. - BusyBox has
wget too, with far fewer options; curl is the one the answers online assume.
See also links, rsync, ssh
ip Show and change network interfaces, addresses and routes.
Network · busybox 1.37.0 · Alpine's base system · man busybox(1) · home
a BusyBox applet: busybox ip --help, and BusyBox's page
On Copal: The quickest answer to "what is my address" and "is the wifi up". On Copal it is BusyBox's applet: the common part of iproute2's ip, not all of it.
Use
ip addr shows each interface and its addresses, ip route where traffic goes, ip link whether an interface is up. Changes made with it last until the next restart; the lasting configuration is /etc/network/interfaces.
Examples
ip addrevery interface and its addresses
ip -4 -o addrIPv4 only, one line each
ip addr show wlan0one interface
ip routethe default gateway is the 'default via' line
doas ip link set wlan0 upbring an interface up
ip neighmachines seen on the local network
doas rc-service networking restartre-apply /etc/network/interfaces
Options
addr [show DEV]- addresses (a, address)
route- the routing table (r)
link- interfaces, up or down, and their MAC addresses
neigh- the neighbour (ARP) table
-f inet- one address family: inet, inet6 (-4 and -6 work too)
-o- one line per entry, for grep
link set DEV up- bring DEV up; down to take it down
Notes
- BusyBox's
ip lacks the newer options: ip -br a, -c and -j print its usage instead. Use ip -o addr for the short form. - No IPv4 address on wlan0 means it is not associated, or DHCP has not answered: check
iw dev wlan0 link before blaming DHCP. ifconfig is here too (BusyBox), for the habit; ip is what Alpine's own scripts use./etc/network/interfaces is read by ifup and ifdown (ifupdown-ng): auto wlan0 and iface wlan0 inet dhcp make it come up at boot.
See also iw, wpa_cli, ssh, busybox
iw Look at and control wireless interfaces: scan, link, signal, country.
Network · iw 6.17 · stage 10 · Wireless, audio, capture and disks · man iw(8) · home
needs libnl3
On Copal: Stage 10 installs it with wpa_supplicant for the Pi's wifi. It answers what the radio sees and how well it is connected; joining a protected network is wpa_supplicant's job, not iw's.
iw [ OPTIONS ] { help [ command ] | OBJECT COMMAND }
OBJECT := { dev | phy | reg }
OPTIONS := { --version | --debug }
Use
Name a wireless interface (wlan0) and ask it something: which networks it can hear, what it is connected to and at what signal, which channels the country allows.
Examples
iw devthe wireless interfaces
doas iw dev wlan0 scan | grep SSIDthe networks in range
iw dev wlan0 linkconnected to what, signal, speed
iw dev wlan0 station dumpthe access point's statistics
iw reg getthe regulatory country in force
doas iw reg set GBset it (use your own country)
iw list | lesseverything the chip can do
Options
dev- list wireless interfaces
dev IF scan- scan for networks (root)
dev IF link- the current connection
dev IF station dump- per-station statistics
reg get / reg set CC- read or set the regulatory country
list- the hardware's capabilities
phy- the radios, as distinct from interfaces
Notes
- A scan needs root: without it, "Operation not permitted (-1)". "Device or resource busy (-16)" means the interface is down --
doas ip link set wlan0 up -- or blocked: rfkill list, then doas rfkill unblock wifi. - 5 GHz networks missing from a scan often means no country is set: the radio then allows only what is legal everywhere.
iw dev wlan0 connect joins open networks only. For WPA, which is nearly every network, use wpa_supplicant -- setup-interfaces or wpa_cli.- The Pi Zero (the first one) has no wifi at all; the Zero W and Zero 2 W do.
See also wpa_cli, wpa_passphrase, ip
ssh Log in to another machine, or run one command on it, over an encrypted connection.
Network · openssh-client-default 10.3_p1 · stage 1 · Apply the setup-alpine answers · man ssh(1) · home
needs openssh-keygen, openssh-client-common, !openssh-client-krb5, libcrypto3, zlib
On Copal: How a Copal machine is reached from the Mac, and how it reaches GitHub and the others. Stage 1 turns on sshd; stage 6 authorises the Mac's key, so the first login needs no password.
ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
[-i identity_file] [-J destination] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd]
[-o option] [-P tag] [-p port] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] destination [command [argument ...]]
ssh [-Q query_option]
Use
ssh user@host opens a shell there; ssh host command runs one command and returns. The same connection carries files (scp, rsync, sshfs) and ports (-L). A key instead of a password is set up once, with ssh-keygen and ssh-copy-id.
Examples
ssh you@192.168.1.20a shell on another machine
ssh pi 'df -h /'one command, then back
ssh -p 2222 you@example.orgsshd on another port
ssh -L 8080:localhost:80 pithe Pi's port 80 as localhost:8080 here
ssh -J gateway you@insidethrough a machine in between
ssh-copy-id you@192.168.1.20install your key there, once
ssh -v pisay why a connection fails
Options
-p PORT- connect to this port
-i FILE- use this private key
-L L:HOST:R- forward local port L to HOST:R, from the far side
-R R:HOST:L- the reverse: a port there comes back here
-J HOST- jump through HOST first
-N- no command: just hold the forwards open
-t- force a terminal, for an interactive program: ssh -t pi htop
-o KEY=VALUE- any config option, for once
-v- debug output; -vvv for more
Notes
~/.ssh/config saves typing: a Host pi block with HostName, User and Port makes ssh pi enough, and scp, rsync and git use it too.- "REMOTE HOST IDENTIFICATION HAS CHANGED" after reinstalling a card is expected: the new system made new host keys. Remove the old one with
ssh-keygen -R HOST, then connect again. Anywhere else, stop and ask why. - A frozen session (the far side went away) does not answer Ctrl-C. Type Enter, then
~. -- ssh's escape -- and it closes. - Password refused although it is right? Copal can turn password logins off:
copal-ssh status says what is in force on the machine you are connecting to.
See also ssh-keygen, rsync, tmux, curl
ssh-keygen Make SSH keys, and inspect, fix or forget them.
Network · openssh-keygen 10.3_p1 · stage 1 · Apply the setup-alpine answers · man ssh-keygen(1) · home
needs libcrypto3
On Copal: A key is what lets this machine push to GitHub and log in to the others without a password. Stage 7 tells you to make one when a checkout falls back to HTTPS; stage 16's fleet reads its host certificates with it.
ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile] [-m format]
[-N new_passphrase] [-O option] [-t ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]
[-w provider] [-Z cipher]
ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase] [-P old_passphrase]
[-Z cipher]
ssh-keygen -i [-f input_keyfile] [-m key_format]
ssh-keygen -e [-f input_keyfile] [-m key_format]
ssh-keygen -y [-f input_keyfile]
ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]
ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
ssh-keygen -B [-f input_keyfile]
ssh-keygen -D pkcs11
ssh-keygen -F hostname [-lv] [-f known_hosts_file]
ssh-keygen -H [-f known_hosts_file]
...
Use
Make a key pair: a private half that stays in ~/.ssh and a .pub half you give away. Beyond that it answers questions about keys -- fingerprints, certificates -- and removes stale hosts from known_hosts.
Examples
ssh-keygen -t ed25519 -C "$(hostname)"a new key (Enter for the defaults)
cat ~/.ssh/id_ed25519.pubthe half to paste into GitHub
ssh-keygen -l -f ~/.ssh/id_ed25519.pubits fingerprint
ssh-keygen -R 192.168.1.20forget a host whose key changed
ssh-keygen -p -f ~/.ssh/id_ed25519add or change the passphrase
ssh-keygen -y -f ~/.ssh/id_ed25519rebuild a lost .pub from the private key
Options
-t TYPE- the key type: ed25519 (use this), rsa, ecdsa
-C COMMENT- a label stored in the key: who and where
-f FILE- the key file to make or read
-N PHRASE- the passphrase, given on the command line ('' for none)
-l- show a key's fingerprint
-R HOST- remove HOST from known_hosts
-F HOST- find HOST in known_hosts
-p- change a key's passphrase
-y- print the public key of a private one
-L- show a certificate's contents
Notes
- The private file (
id_ed25519, no .pub) never leaves the machine. If it is ever pasted anywhere, make a new pair. - ssh refuses a private key others can read: "UNPROTECTED PRIVATE KEY FILE".
chmod 600 ~/.ssh/id_ed25519 and chmod 700 ~/.ssh. - Use ed25519: short, fast, and accepted everywhere Copal connects to. Only very old servers need
-t rsa -b 4096. - Running it again over an existing key asks before overwriting -- say no unless you mean to replace the key everywhere it is installed.
See also ssh, git
wpa_cli Talk to the running wpa_supplicant: scan, add a network, see the state.
Network · wpa_supplicant 2.11 · stage 10 · Wireless, audio, capture and disks · man wpa_cli(8) · home
needs libcrypto3, dbus-libs, libnl3, pcsc-lite-libs, libssl3
On Copal: Copal's wifi is wpa_supplicant (stage 10), not NetworkManager, so there is no nmcli. wpa_cli is how to join a new network or see why one will not connect, without editing files and restarting.
wpa_cli [ -p path to ctrl sockets ] [ -g path to global ctrl_interface socket ] [ -i ifname ]
[ -hvB ] [ -a action file ] [ -P pid file ] [ -G ping interval ] [ command ... ]
Use
With a command, run it and return; with none, an interactive prompt where the same commands work, with tab completion and live events. Add a network, set its name and password, enable it, and save.
Examples
wpa_cli -i wlan0 statusconnected? to what, with which address
wpa_cli -i wlan0 scanstart a scan...
wpa_cli -i wlan0 scan_results...and read it
wpa_cli -i wlan0 list_networksthe networks it knows
wpa_cli -i wlan0 add_networka new one: prints its number, say 1
wpa_cli -i wlan0 set_network 1 ssid '"Home WiFi"'
wpa_cli -i wlan0 set_network 1 psk '"the password"'
wpa_cli -i wlan0 enable_network 1try it
wpa_cli -i wlan0 save_configkeep it across reboots
Options
-i IF- the interface, wlan0
-p DIR- where the control sockets are (/run/wpa_supplicant)
status- state, SSID, address
scan, scan_results- scan, then list what was found
list_networks- the configured networks and their numbers
add_network- a new empty network; prints its number
set_network N KEY VALUE- ssid, psk, key_mgmt, priority...
enable_network N- allow it; select_network N uses only it
remove_network N- forget it
save_config- write the configuration file
reconfigure- re-read the configuration file
Notes
- "Failed to connect to non-global ctrl_ifname": wpa_supplicant has no control socket. The file
setup-interfaces writes has no ctrl_interface line; add ctrl_interface=DIR=/run/wpa_supplicant GROUP=wheel and update_config=1 at the top of /etc/wpa_supplicant/wpa_supplicant.conf, then doas rc-service wpa_supplicant restart. - The quotes are both needed:
'"Home WiFi"'. The outer pair is for the shell; the inner pair tells wpa_supplicant it is text, not hex. save_config fails without update_config=1 in the file, and the network is forgotten at the next restart.- The password typed into
set_network lands in the shell's history. wpa_passphrase avoids that.
See also wpa_passphrase, iw, ip
wpa_passphrase Turn a wifi name and password into a network block for wpa_supplicant.
Network · wpa_supplicant 2.11 · stage 10 · Wireless, audio, capture and disks · man wpa_passphrase(8) · home
needs libcrypto3, dbus-libs, libnl3, pcsc-lite-libs, libssl3
On Copal: Alpine's own setup-interfaces uses it to write Copal's wifi configuration, and it is the quick way to add a second network by hand without leaving the password in the file as plain text.
wpa_passphrase [ ssid ] [ passphrase ]
Use
Give it the network's name; type the password when it asks. It prints a network={...} block with the password hashed into a 64-digit psk, ready to add to /etc/wpa_supplicant/wpa_supplicant.conf.
Examples
wpa_passphrase "Home WiFi"type the password; prints the block
wpa_passphrase "Home WiFi" | doas tee -a /etc/wpa_supplicant/wpa_supplicant.conf
doas rc-service wpa_supplicant restartuse the new network
wpa_passphrase "Home WiFi" 'the password'password as an argument (see Notes)
Options
SSID- the network's name; quote it if it has spaces
PASSPHRASE- the password, 8 to 63 characters; omit it to be asked
Notes
- The block it prints includes the password in clear, as a comment (
#psk="..."). Delete that line from the file -- setup-interfaces does the same. - A password on the command line is saved in the shell's history. Leave it off and type it at the prompt instead; piping it in does not work ("Not a tty").
- The hash depends on the name: rename the network and the
psk must be made again. - Open networks and WPA3-only networks need a block written by hand (
key_mgmt=NONE, or key_mgmt=SAE with sae_password).
See also wpa_cli, iw, setup-alpine
Science
gnuplot Plot functions and data files, in a window, to an image, or as text in the terminal.
Science · command-line tool · gnuplot 6.0.4 · stage 12 · The application catalogue · man gnuplot(1) · home
needs libx11, cairo, libcerf, libgd, glib, pango, readline, libwebp
On Copal: The catalogue's plotter, and the one Octave, Maxima and ngspice draw through. A plot of a data file is one line.
gnuplot [X11 options] [options] [file ...]
Use
plot a function or a file's columns. Where the plot goes is the terminal setting: a window, a PNG or SVG file, or the text terminal itself (dumb, or sixelgd in a terminal that shows sixel images).
Examples
gnuplot -p -e 'plot sin(x)'a window that stays open
gnuplot -e 'set terminal dumb; plot sin(x)'as text, over SSH
gnuplot -e "set terminal pngcairo; set output 'p.png'; plot 'data.txt' using 1:2 with lines"
gnuplot script.gpa file of commands
gnuplotthe prompt
plot 'data.csv' using 1:3 with lines (at the prompt) columns 1 and 3
set datafile separator ',' for CSV
replot draw again after a change
Options
-e 'CMDS'- run the commands (separated by ;)
-p- persist: keep the window after gnuplot exits -c FILE ARGS run FILE with arguments
-d- ignore any ~/.gnuplot initialisation file
Notes
- The terminals this build has:
x11 (a window), pngcairo, svg, sixelgd, kittycairo, and dumb. set terminal lists them all. - A CSV needs
set datafile separator ','; otherwise columns are split on whitespace.
See also octave, maxima, ngspice, python3
gp PARI/GP: a calculator for number theory -- huge integers, primes, factoring, elliptic curves.
Science · terminal program · pari 2.17.3 · stage 12 · The application catalogue · man gp(1) · home
needs pari-libs, readline
On Copal: The catalogue's number-theory system: exact arithmetic on numbers with thousands of digits, fast, at an interactive prompt.
gp [-s stacksize] [-p primelimit] [--emacs] [-f|--fast] [-q|--quiet] [-D|--default key=val]
[--help] [--test] [--texmacs] [--version] [--version-short] [ file1 file2 ...]
Use
Type an expression at the ? prompt and get the answer. Integers are exact at any size; \p sets the decimal precision for everything else.
Examples
gpthe prompt
echo 'factor(2^128+1)' | gp -qone computation, quietly
gp -q script.gprun a file
factor(2^67 - 1) (at the prompt) factor a number
isprime(10^100 + 267) is it prime?
nextprime(10^50) the next prime
\p 100 100 digits of precision; Pi then shows them
?factor help on one function; \q quit
Options
-q, --quiet- no banner
-s SIZE- the initial stack size
-p N- precompute primes up to N
--default KEY=VAL- set a default at start: --default realprecision=50
Notes
- "the PARI stack overflows": it grows the stack itself up to
parisizemax; for very large computations, default(parisizemax, "2G"). ? alone lists the help sections; ??factor is the long manual entry.
See also maxima, Singular
maxima Computer algebra: solve, simplify, differentiate, integrate -- exactly, with symbols.
Science · terminal program · maxima 5.48.1 · stage 12 · The application catalogue · man maxima(1) · home
needs texinfo, shared-mime-info, ecl
On Copal: The catalogue's symbolic mathematics: the answer as a formula, not a number -- integrals, limits, series, systems of equations.
maxima [options]
rmaxima [options]
xmaxima [options]
Use
Type expressions at the (%i1) prompt, each ending with ; (show the result) or $ (hide it). % is the last result. Everything stays exact until you ask for a number with float().
Examples
maximathe prompt
maxima --batch-string='integrate(x*sin(x), x);'one computation, then exit
maxima -b work.macrun a file of commands
diff(x^3*sin(x), x); (at the prompt) differentiate
integrate(1/(1+x^2), x, 0, 1); a definite integral: %pi/4
solve([x+y=3, x-y=1], [x,y]); a system of equations
float(%pi); a number
quit(); leave
Options
-b, --batch FILE- run FILE and exit
--batch-string=STR- run STR and exit
-q, --quiet- no banner
-r, --run-string=STR- run STR, then stay at the prompt
Notes
- Every input ends with
; or $. Without one, Maxima waits for more. plot2d(sin(x), [x, 0, 6]) draws with gnuplot.- It comes from Alpine's testing repository (
maxima@testing).
See also octave, gp, Singular, gnuplot
octave GNU Octave: numerical computing in a language compatible with MATLAB.
Science · terminal program · octave 11.1.0 · stage 12 · The application catalogue · man octave(1) · home
needs qt6-qtbase-sqlite, openblas, mesa-gl, glu, graphicsmagick-c++, graphicsmagick, qt6-qtbase, qt6-qt5compat
On Copal: The catalogue's MATLAB-alike: matrices, linear algebra, signal processing and plots, and most MATLAB scripts run unchanged.
octave [options]... [file]
Use
Type at the >> prompt, or run a .m script. Everything is a matrix; ; at the end of a line stops it printing the result.
Examples
octavethe prompt
octave script.mrun a script
octave --eval 'disp(inv([2 1; 1 3]))'one expression
octave --no-guithe terminal prompt, never a window
A = [1 2; 3 4]; (at the prompt) a matrix
x = A \ [5; 6] solve A x = b
plot(sin(0:0.1:6)) a plot, in a window
pkg list the installed packages; exit leave
Options
--eval CODE- run CODE and exit
--no-gui- the command line, no window
-q, --quiet- no banner
-W, --no-window-system- no graphics at all (plots fail; for scripts)
--path DIR- add DIR to the function search path
Notes
- Plots open a window, so they need the desktop. Over SSH, use
graphics_toolkit gnuplot and set terminal dumb for ASCII, or print -dpng plot.png to save the figure. - Octave-Forge packages (
pkg install -forge NAME) build from source and need build-base; several are in Alpine as octave-NAME.
See also python3, R, gnuplot, maxima
pdflatex Typeset a LaTeX document straight to PDF.
Science · command-line tool · texlive 2026.0 · stage 12 · The application catalogue · man pdflatex(1) · home
needs ghostscript, perl, texmf-dist, texmf-dist-latex, libx11, cairo, gmp, icu-libs
On Copal: TeX Live, for papers, theses, letters and anything with equations. Stage 14 asks which: texlive, a few hundred MB, or texlive-full, about 4 GB, with every package there is.
pdftex [options] [&format] [file|\commands]
Use
Write the document as a .tex file; pdflatex turns it into a .pdf. Cross-references, a table of contents and citations need a second run, because the first only records where things are.
Examples
pdflatex paper.texpaper.pdf
pdflatex paper.tex && pdflatex paper.textwice: references settle
pdflatex -interaction=nonstopmode paper.texdo not stop at errors
latexmk -pdf paper.texas many runs as needed, bibliography too
kpsewhich tikz.styis this package installed?
Options
-interaction=nonstopmode- carry on through errors, no prompt
-halt-on-error- stop at the first error
-output-directory=DIR- write the PDF and logs there
-jobname=NAME- name the output NAME.pdf
-shell-escape- let the document run commands (minted needs it)
Notes
- "File
tikz.sty' not found" means the package is not installed. With the smaller texlive, add a collection: doas apk add texmf-dist-pictures (TikZ), texmf-dist-latexextra` (most others). - At an error it waits at a
? prompt: x Enter leaves. The real message is a few lines above, and in the .log. - Keep
-shell-escape for documents you wrote: it lets the document run programs.
See also gnuplot, octave, maxima
python3 The Python interpreter: scripts, a calculator, and a large standard library.
Science · command-line tool · python3 3.14.7 · stage 4 · X.Org, i3, a terminal and a browser · man python3(1) · home
needs libssl3, libexpat, libbz2, libcrypto3, libffi, gdbm, xz-libs, mpdecimal
On Copal: Several of Copal's own tools are Python, and so is a good share of what people run on a Pi. Stage 4 installs it; the catalogue's Science section adds the numerical packages.
python [ -B ] [ -b ] [ -d ] [ -E ] [ -h ] [ -i ] [ -I ]
[ -m module-name ] [ -q ] [ -R ] [ -O ] [ -OO ] [ -P ] [ -s ] [ -S ] [ -u ]
[ -v ] [ -V ] [ -W argument ] [ -x ] [ -X option ] [ -? ]
[ --check-hash-based-pycs default | always | never ]
[ --help ] [ --help-env ] [ --help-xoptions ] [ --help-all ]
[ -c command | script | - ] [ arguments ]
Use
Run a script, or start the interactive prompt and type. Third-party packages come from apk first (py3-NAME), and from pip inside a virtual environment when apk has not got them.
Examples
python3the interactive prompt; Ctrl-D leaves
python3 script.pyrun a script
python3 -c 'print(2**64)'one line
python3 -m http.server 8000serve this directory on port 8000
python3 -m venv .venva private environment for a project...
. .venv/bin/activate...enter it (deactivate to leave)
python3 -m json.tool data.jsonpretty-print JSON
python3 -m pdb script.pystep through it in the debugger
Options
-c CMD- run CMD
-m MODULE- run a module as a script: venv, http.server, pdb, json.tool, pip
-i- stay at the prompt after the script ends
-u- unbuffered output (for logs and pipes)
-V- the version
Notes
pip install outside a virtual environment says "externally-managed-environment". That is deliberate: the system's Python belongs to apk. apk add py3-NAME if it exists, or a venv.- Packages with C parts often have no ready wheel for musl and build from source:
apk add build-base python3-dev first. - Python 2 is gone:
python is Python 3 too, but scripts written for Copal say python3, which works on every system that has it.
See also pip, gdb, nvim
R The R language for statistics and graphics.
Science · terminal program · R 4.6.0 · stage 12 · The application catalogue · man R(1) · home
needs R-mathlib, tzdata, openblas, libx11, libxmu, libxt, libbz2, cairo
On Copal: The catalogue's statistics environment: data frames, models, tests and plots, with CRAN's twenty thousand packages behind it.
R [options] [< infile] [> outfile]
R CMD command [arguments]
Use
Type at the > prompt, or run a script with Rscript. Data frames hold tables; summary(), lm() and plot() do most of the everyday work.
Examples
Rthe prompt
Rscript analysis.Rrun a script
R -q -e 'summary(mtcars)'one expression
R --vanillano saved workspace, no profiles
d <- read.csv("data.csv") (at the prompt) load a table
summary(d) the statistics of each column
fit <- lm(y ~ x, data=d) a linear model; summary(fit)
install.packages("ggplot2") a package from CRAN
q() leave
Options
-q, --quiet- no banner
-e EXPR- evaluate EXPR (with R -q -e)
--vanilla- no profile, no saved workspace
--no-save- do not save the workspace on exit
-f FILE- read commands from FILE
Notes
- The system library is not writable: the first
install.packages() offers a personal library in your home -- answer yes. - Packages with C or Fortran compile from source on Alpine (no binary packages for musl) and need
build-base and gfortran; the first install of a big one takes a while. q() asks whether to save the workspace; n, or it reloads into every later session.
See also python3, octave, gnuplot
Singular Computer algebra for polynomials: Gröbner bases, ideals, singularities.
Science · terminal program · singular 4.4.1_p5 · stage 12 · The application catalogue · man Singular(1) · home
needs python3, cddlib, flint, gmp
On Copal: The catalogue's polynomial-algebra system, the tool of commutative algebra and algebraic geometry. The command has a capital S.
Singular [options] [file1 [file2 ...]]
ESingular [options] [file1 [file2 ...]]
TSingular [options] [file1 [file2 ...]]
Use
Declare a ring -- the field, the variables, the ordering -- then work in it with polynomials and ideals. Every statement ends with ;.
Examples
Singularthe prompt (capital S)
Singular -q script.singrun a file
ring r = 0, (x,y,z), dp; (at the prompt) rational coefficients, x y z
ideal I = x2 - y, y2 - z; an ideal (x2 is x^2)
std(I); its Gröbner basis
help std; help on a command
quit; leave
Options
-q, --quiet- no banner, and quit at the end of a file
-b, --batch- batch mode
--no-rc- do not read the .singularrc file
-c CMD- run CMD first
Notes
- The command is
Singular; singular is not found. - In a ring declared with short variable names,
x2y means x^2*y.
See also maxima, gp
Sharing
croc Send a file or a folder to another computer, with a code phrase, from one command.
Sharing · command-line tool · croc 10.2.2 · stage 12 · The application catalogue · home
On Copal: The catalogue's quickest way to hand a file to someone: no shared network, accounts or server set-up. Encrypted end to end.
USAGE:
croc [GLOBAL OPTIONS] [COMMAND] [COMMAND OPTIONS] [filename(s) or folder]
USAGE EXAMPLES:
Use
The sender runs croc send FILE and gets a code phrase. The receiver runs croc with that phrase, on any machine with croc, and the file arrives. Both sides meet through a relay, which never sees the contents.
Examples
croc send photo.jpgprints a code phrase to pass on
croc send ~/Documents/reporta whole folder
croc send --text 'meet at 3'a line of text
CROC_SECRET=7-lemon-orbit-jazz crocreceive, with the phrase you were given
Options
send FILE...- send files or folders
send --text T- send a line of text instead of a file
send --code P- choose the phrase yourself
--yes- accept without asking (receiving)
--relay ADDR- use another relay, such as your own
--classic- accept the phrase as an argument (less safe)
Notes
- On Linux the phrase goes in
CROC_SECRET, not on the command line, where other users could see it in the process list: croc refuses it as an argument and says so. --classic restores the old way. - The default relay is a public one run by croc's author;
croc relay runs your own.
See also rsync, syncthing, darkhttpd
darkhttpd Serve a folder over HTTP, with one command and no configuration.
Sharing · command-line tool · darkhttpd 1.17 · stage 12 · The application catalogue · home
On Copal: The catalogue's smallest web server: share a folder of files on the LAN for a minute, or preview a static site from its output folder.
usage: /usr/bin/darkhttpd /path/to/wwwroot [flags]
flags: --port number (default: 8080, or 80 if running as root)
Specifies which port to listen on for connections.
Use
Give it a folder; it serves it on port 8080 until Ctrl-C, with a listing of the files where there is no index.html.
Examples
darkhttpd ~/Publichttp://this-machine:8080/
darkhttpd public --port 8000a built site, on port 8000
darkhttpd . --addr 127.0.0.1this machine only
darkhttpd ~/Public --no-listingno folder listings
Options
--port N- the port (default 8080)
--addr IP- listen on one address only (default: all)
--no-listing- do not list folders without an index.html
--index FILE- the index file (default index.html)
--log FILE- write an access log
Notes
- By default it listens on every address, so anyone on the network can read the folder.
--addr 127.0.0.1 keeps it to this machine. - It serves files as they are: no PHP, no uploads, no passwords.
- A service is installed too (
/etc/init.d/darkhttpd) for serving a folder permanently; /etc/conf.d/darkhttpd says which.
See also hugo, zola, croc, python3
rsync Copy and synchronise files, locally or over SSH, sending only differences.
Sharing · command-line tool · rsync 3.5.0 · stage 12 · The application catalogue · man rsync(1) · home
needs acl-libs, lz4-libs, popt, libxxhash, zlib, zstd-libs
On Copal: Stage 11's snapshots are rsync, and so is moving a home directory to a new card or a backup to another machine; the catalogue carries it for copying trees between machines.
Local:
rsync [OPTION...] SRC... [DEST]
Access via remote shell:
Pull:
rsync [OPTION...] [USER@]HOST:SRC... [DEST]
Push:
rsync [OPTION...] SRC... [USER@]HOST:DEST
Access via rsync daemon:
Pull:
rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push:
...
Use
Keep one tree identical to another. Only changed files cross, and only the changed parts of them, so the second run over a large tree takes seconds.
Examples
rsync -av ~/Photos/ /media/usb/Photos/copy a tree, keeping times and modes
rsync -avz --delete ~/code/ pi:code/mirror to another machine over SSH
rsync -avn --delete src/ dst/dry run: what would change
rsync -aP big.iso pi:/tmp/resumable, with a progress bar
rsync -aHAX / /media/snapshots/today/a whole system: links, ACLs, attributes
Options
-a- archive: recursive, keeps symlinks, modes, times, owner, group
-v- name each file
-z- compress in transit (for a slow link, not a LAN)
-n- dry run
-P- --partial --progress: keep partial files, show progress
--delete- remove files in the destination that the source lacks
-e 'ssh -p 2222'- the remote shell, with its options --exclude=PATTERN skip matching paths
-H -A -X- keep hard links, ACLs and extended attributes
Notes
- The trailing slash is the whole question.
src/ copies the contents of src; src copies the directory itself, into the destination. --delete with the wrong direction or a missing slash deletes the wrong files. Run it with -n first.-a does not keep hard links, ACLs or extended attributes; add -HAX for a system copy, as the snapshot stage does.
See also ssh, lftp
smbd Samba's file server: share folders with Windows and macOS machines over SMB.
Sharing · command-line tool · samba-server 4.23.8 · stage 12 · The application catalogue · man smbd(8) · home
needs samba-client-libs, samba-common, samba-common-server-libs, samba-libs, samba-util-libs, libauth-samba, libwbclient, acl
On Copal: The catalogue's way to make the Pi's files appear in Finder or Explorer like any network drive. Alpine's default configuration already shares each user's home folder, once the user has a Samba password.
smbd [-D|--daemon] [-i|--interactive] [-F|--foreground] [--no-process-group]
[-b|--build-options] [-p <port number(s)>] [-P <profiling level>] [-d <debug level>]
[--debug-stdout] [--configfile=<configuration file>] [--option=<name>=<value>]
[-l|--log-basename <log directory>] [--leak-report] [--leak-report-full] [-V|--version]
Use
Give your account a Samba password, start the service, and connect from the other machine: smb://PI/yourname in macOS Finder (Cmd-K), or \\PI\yourname in Windows Explorer. More shares are sections in /etc/samba/smb.conf.
Examples
doas smbpasswd -a $USERa Samba password for your account (once)
doas rc-service samba startstart it now
doas rc-update add sambaand at every boot
testparm -scheck smb.conf, and print what is in force
smbd -b | headhow this Samba was built
Options
-F, --foreground- run in the foreground (for debugging)
-i, --interactive- run interactively, logging to the terminal
-s, --configfile=F- another configuration file
-b, --build-options- print the build options
-V, --version- the version
Notes
- The Samba password is separate from your login password:
smbpasswd sets it, and a share refuses you until it is set. - The service is
samba, which starts smbd and nmbd together; the command itself is rarely run by hand. - A share for a folder of its own:
[music] then path = /home/you/Music and read only = no in smb.conf, then doas rc-service samba restart.
See also sshfs, syncthing, rc-service
sshfs Mount a folder from another machine over SSH, and use it like a local one.
Sharing · command-line tool · sshfs 3.7.6 · stage 12 · The application catalogue · man sshfs(1) · home
needs openssh-client, fuse3, fuse3-libs, glib
On Copal: The catalogue's network folder with nothing to set up on the other side: anywhere you can ssh to, you can mount. No root needed on Copal.
To mount a filesystem:
sshfs [user@]host:[dir] mountpoint [options]
If host is a numeric IPv6 address, it needs to be enclosed in square brackets.
To unmount it:
fusermount3 -u mountpoint # Linux
umount mountpoint # OS X, FreeBSD
Use
Mount a remote folder onto an empty local one; programs then read and write it as if it were here. Unmount with fusermount3 -u when done.
Examples
mkdir -p ~/mnt/pi
sshfs pi:/home/you/Music ~/mnt/pimount
sshfs -o reconnect pi:Music ~/mnt/pisurvive a dropped connection
sshfs -p 2222 you@example.org:/srv ~/mnt/srvsshd on another port
fusermount3 -u ~/mnt/piunmount
Options
-p PORT- the SSH port
-o reconnect- reconnect after the connection drops
-o idmap=user- show the remote files as yours
-o follow_symlinks- follow links on the remote side
-f- stay in the foreground (to see errors)
Notes
- Unmounting is
fusermount3 -u, not umount: a plain user may not umount. - Everything goes through ssh, so
~/.ssh/config hosts and keys work: sshfs pi: is enough when pi is a host there. - A folder full of large files is slow to list over a slow link; for copying many files,
rsync is faster.
See also ssh, smbd, rsync
syncthing Keep folders in sync between your machines, directly, with no server in between.
Sharing · command-line tool · syncthing 2.1.0 · stage 12 · The application catalogue · man syncthing(1) · home
needs sqlite-libs
On Copal: The catalogue's continuous sync: a folder on the Pi and the same folder on the Mac or a phone stay identical, over the LAN or the internet, encrypted.
syncthing [serve]
[--home=<dir> | --config=<dir> --data=<dir>]
[--allow-newer-config] [--audit] [--auditfile=<file|-|-->]
[--db-maintenance-interval=<interval>]
[--db-delete-retention-interval=<interval>]
[--gui-address=<address>] [--gui-apikey=<key>]
[--log-level=<level>] [--log-file=<filename>]
[--log-max-old-files=<num>] [--log-max-size=<num>]
[--log-format-timestamp=<format>] [--no-log-format-level-string]
[--log-format-level-syslog]
[--no-browser] [--no-console]
[--no-port-probing] [--no-restart] [--no-upgrade]
[--paused] [--unpaused]
[--version] [--help] [--debug-*]
...
Use
Run it as yourself; it serves a web page at 127.0.0.1:8384 where you add the other machines (by their device ID) and choose which folders to share. After that it works in the background.
Examples
syncthingstart it (and open the web page)
syncthing serve --no-browserstart without opening a browser
syncthing device-idthis machine's ID, to give the others
syncthing pathswhere its config and database are
syncthing browseropen its web page in the browser
Options
serve- run it (the default command) --no-browser with serve: do not open the web page --gui-address=URL with serve: the page elsewhere, e.g. 0.0.0.0:8384
device-id- print this device's ID
paths- where its files are
-H, --home=PATH- another config and database directory
Notes
- Run it as yourself, not the system service: the service runs as the user
syncthing, which cannot read or write your home folder. exec-once = syncthing serve --no-browser in ~/.config/hypr/local.conf starts it with the desktop. - To see the web page from another machine, an SSH tunnel keeps it private:
ssh -L 8384:127.0.0.1:8384 pi, then browse to localhost:8384 there. - A deleted file is deleted everywhere. Turn on file versioning for a folder if that worries you.
See also rsync, unison, croc
unison Two-way file synchronisation: changes on either side are carried to the other.
Sharing · command-line tool · unison 2.54.0 · stage 12 · The application catalogue · man unison(1) · home
On Copal: The catalogue's two-way sync, run when you choose -- for a laptop and a Pi that both change the same folder. Where rsync mirrors one way, unison merges both, and asks about conflicts.
unison [options]
unison root1 root2 [options]
unison profilename [options]
Use
Name two roots -- local folders, or one over ssh -- and unison compares them with what it saw last time, proposes what to copy each way, and asks about anything changed on both sides.
Examples
unison ~/docs ssh://pi//home/you/docssync, asking
unison -batch ~/docs ssh://pi//home/you/docsno questions: skip conflicts
unison -auto ~/docs /media/usb/docsaccept non-conflicts, ask the rest
unison workthe profile ~/.unison/work.prf
Options
-batch- ask nothing; conflicting files are skipped
-auto- accept the default actions, ask only about conflicts
-ui text- the text interface (the default here)
-path P- sync only P, within the roots
-ignore P- leave P out (as a pattern) -prefer ROOT on a conflict, take ROOT's version
Notes
- Both machines need the same unison version -- 2.54 here -- or it refuses to talk.
- The double slash in
ssh://pi//home/you/docs is an absolute path; a single one would be relative to your home on pi. - A profile saves the roots and options:
root = ... lines in ~/.unison/NAME.prf, then unison NAME.
See also rsync, syncthing, ssh
System
btop A resource monitor with graphs: CPU, memory, disks, network and processes, live.
System · terminal program · btop 1.4.6 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · on the Copal Apps shelf · man btop(1) · home
On Copal: The store's richer htop: history graphs for every core, the disks and the network in one screen, with the mouse working throughout.
btop [-c file] [-d] [-f filter] [-l] [-p id] [-t] [-u ms] [--force-utf] [--themes-dir dir]
btop [--default-config | {-h | --help} | {-V | --version}]
Use
Start it; boxes show CPU, memory, disks, network and processes. Click or use the keys; Esc opens the menu with options and help. Numbers 1 to 4 toggle the boxes.
Examples
btopeverything
btop -p 1start with preset 1
btop -f firefoxprocesses filtered to firefox
btop -tplain console mode, 16 colours
btop -u 500update every half second
1 2 3 4 (in btop) show or hide cpu, memory, network, processes
f filter processes
k kill the selected process (asks first)
Esc q the menu / quit
Options
-p, --preset N- start with preset N (0-9)
-f, --filter TEXT- an initial process filter
-t, --tty- console mode: ANSI graph symbols, 16 colours
-l, --low-color- 256 colours, no true colour
-u, --update MS- the update interval
-c, --config FILE- another config file
Notes
- Its settings are saved from the menu to
~/.config/btop/btop.conf; btop --default-config prints the defaults. - On the Linux console (no desktop)
-t gives graphs that draw correctly.
See also htop, copal-tm
busybox One small program that is three hundred commands: sh, sed, awk, vi, wget...
System · busybox 1.37.0 · Alpine's base system · man busybox(1) · home
On Copal: Alpine's base system is BusyBox, and so is Copal's. The fuller levels pull in GNU coreutils, grep and tar beside it, but sed, awk, find, xargs, vi, wget, ping, nc, ip, blkid and the shell /bin/sh stay BusyBox's.
Use
Mostly invisible: each applet is a link to /bin/busybox, and runs as whatever name it was called by. Call busybox by name to see what it provides, to read an applet's help, or to run the BusyBox version of a command a fuller package has replaced.
Examples
busybox --listevery applet it provides
ls -l $(command -v sed)-> /bin/busybox: sed is BusyBox here
busybox sed --helpan applet's options, and only those
busybox wget -O- https://example.com # the applet, even if GNU wget is in
apk info -W $(command -v find)BusyBox, or a real package?
Options
--list- the applets, one per line
APPLET --help- that applet's usage: the options it really has
Notes
- The answers online are mostly for GNU. BusyBox applets take fewer options, and some take an option and ignore it:
blkid -s UUID -o value prints the whole line and exits 0 -- it once put a device path where a UUID belonged in Copal's grub.cfg. Check with busybox APPLET --help. /bin/sh is BusyBox ash, not bash: no arrays, no [[ ]] in scripts that start #!/bin/sh. Your login shell may be bash; scripts are not.- There is one manual page for all of it --
man busybox -- and each applet's section in it is short. --help is usually quicker. - Installing the GNU package (
findutils, sed, gawk...) replaces the link; apk del puts BusyBox's back.
See also ip, logread, apk
delta A pager for git diffs: syntax colour, word-level changes, line numbers, side by side.
System · command-line tool · delta 0.19.2 · stage 12 · The application catalogue · home
needs libgit2, oniguruma
On Copal: The catalogue's diff viewer. Set as git's pager, it makes every git diff, show and log -p easier to read, in any terminal.
Usage: delta [OPTIONS] [MINUS_FILE] [PLUS_FILE]
Arguments:
[MINUS_FILE]
Use
Set it once as git's pager, and git uses it for everything it pages. It also reads any diff from a pipe, or compares two files itself.
Examples
git config --global core.pager deltagit's pager, from now on
git config --global interactive.diffFilter 'delta --color-only'and in git add -p
git diffnow through delta
delta -s old.txt new.txttwo files, side by side
diff -u a b | deltaany unified diff
Options
-s, --side-by-side- the two versions in columns
-n, --line-numbers- line numbers down the side
--navigate- n and N jump between files in the pager
--dark / --light- for the terminal's background
--syntax-theme NAME- the colours; --list-syntax-themes lists them
Notes
- Put settings in
~/.gitconfig under [delta]: side-by-side = true, line-numbers = true. - On Copal's light terminal theme,
--light (or light = true in the config) keeps the colours readable.
See also git, tig, lazygit
dmesg Read the kernel's message buffer: hardware, drivers, and what went wrong.
System · dmesg 2.42.3 · stage 5 · Compressed swap in RAM (zram) · man dmesg(1) · home
needs libncursesw
On Copal: The first place to look when a device does nothing -- a USB radio that never appears, a card reader, a wifi chip without firmware. Copal's syslog does not collect kernel messages; they are only here.
dmesg [options]
dmesg --clear
dmesg --read-clear [options]
dmesg --console-level level
dmesg --console-on
dmesg --console-off
Use
Print what the kernel has said since boot, oldest first. Plug a device in, then look at the last lines: they say what it was recognised as, which driver took it, or why none did.
Examples
doas dmesg | tail -20the latest, after plugging something in
doas dmesg -Twith wall-clock times
doas dmesg -wfollow: print new lines as they come
doas dmesg -l err,warnerrors and warnings only
doas dmesg | grep -i usbeverything about USB
Options
-T, --ctime- human-readable timestamps (off after a suspend)
-H, --human- readable and paged, with colour
-w, --follow- wait for new messages
-W, --follow-new- print only new ones
-l, --level LIST- only these levels: emerg, alert, crit, err, warn, notice, info, debug
-k, --kernel- only kernel messages
--since TIME- only lines after TIME
-C, --clear- empty the buffer
Notes
- It needs root on Copal:
kernel.dmesg_restrict is 1, so without doas it says "read kernel buffer failed: Operation not permitted". - The buffer is fixed-size: on a long-running machine the boot messages have been overwritten. Look soon after the event.
- Silence is an answer too. A device that adds no line at all is not being seen -- a cable, power, or (in a VM) a device not passed through.
See also logread, lsblk, rc-status
doas Run one command as root, or as another user.
System · doas 6.8.2 · stage 1 · Apply the setup-alpine answers · man doas(1) · home
On Copal: Copal's only way to root after stage 13 locks the root account. It is OpenBSD's small replacement for sudo; stage 1 installs it and makes your account an administrator by putting it in wheel.
doas [-Lns] [-C config] [-u user] command [args]
Use
Prefix a command that needs root. The rules in /etc/doas.conf and /etc/doas.d/*.conf say who may run what; Copal's say that anyone in wheel may run anything, and asks for the password once per session.
Examples
doas apk add htopone command as root
doas -sa root shell, for several
doas -u radbeeper ida command as another user
doas -C /etc/doas.confcheck a rule file for mistakes
doas -Lforget the remembered password now
Options
-s- run the shell from SHELL as the target user
-u USER- run as USER instead of root
-n- never ask: fail if the rule needs a password
-L- clear the remembered authentication (the persist rules)
-C FILE- parse FILE and report errors; with a command, say permit or deny
Notes
- The LAST matching rule wins. Rule files in
/etc/doas.d are read in alphabetical order -- setup-alpine writes 20-wheel.conf -- which is why Copal names its narrow no-password rules zz-copal-halt.conf and zz-radbeeper.conf: after the general wheel rule, so they match. - A new group takes effect at the next login. After
adduser you wheel, log out and back in before doas will let you through. sudo exists too: doas-sudo-shim turns the usual sudo spellings into doas, for scripts and habits that say sudo. There is no /etc/sudoers.- Always check an edited rule with
doas -C FILE before logging out: a syntax error denies everything, and with root locked that means a rescue from another machine.
See also apk, rc-service
fastfetch The system at a glance, beside a logo: OS, kernel, CPU, memory, desktop, uptime.
System · command-line tool · fastfetch 2.64.2 · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man fastfetch(1) · home
needs hwdata-pci
On Copal: The store's system summary: what this machine is, in one screen -- useful for a bug report, and the screenshot every desktop gets.
fastfetch [OPTIONS...]
Use
Run it; it prints the details beside Alpine's logo. A config file chooses which modules appear and in what order.
Examples
fastfetchthe summary
fastfetch -l nonewithout the logo (for a bug report)
fastfetch -c allevery module it has
fastfetch --gen-configwrite a config to edit
fastfetch --list-moduleswhat it can show
Options
-l, --logo NAME- another logo, or none
-c, --config FILE- a config file or preset (all, neofetch...)
--gen-config [PATH]- write a starting config
--list-modules- list the modules
-s, --structure LIST- which modules, in order: OS:Kernel:Memory
Notes
- Its config is
~/.config/fastfetch/config.jsonc once generated. - It is neofetch's fast successor: the same idea, in C, in a fraction of the time.
See also neofetch, btop, uname
gitui A fast terminal interface for git, in tabs: status, log, files, stashes.
System · terminal program · gitui 0.28.1 · stage 12 · The application catalogue · home
needs libgit2, oniguruma, libssh2, libssl3
On Copal: The catalogue's other git interface: quick to start on large repositories, with every key it takes shown at the bottom.
Use
Start it in a repository. Tabs along the top -- Status, Log, Files, Stashing, Stashes -- switch with the number keys; the bar at the bottom lists the keys for the current view.
Examples
gituithe repository here
gitui -d ~/code/copal/.gitanother repository
1-5 (in gitui) switch tabs
Enter stage or unstage a file (Status)
c commit
Esc / q back / quit
Options
-d, --directory DIR- the git directory to open
-t, --theme FILE- a theme file from its config directory
-l, --logging- write a log (to find a problem)
Notes
- Its key bindings and theme are files in
~/.config/gitui. - It does what git does: a push that needs a password or a key follows git's own settings.
See also git, lazygit, tig
htop An interactive process viewer: CPU, memory, and every process, live.
System · terminal program · htop 3.5.3 · stage 4 · X.Org, i3, a terminal and a browser · man htop(1) · home
needs lsof, libncursesw
On Copal: The task manager on Copal's i3 desktop, where Super+T opens it, and the first thing to run when a machine feels slow.
htop [-dCFhpustvH]
pcp-htop [-dCFhpustvH] [--host/-h host]
Use
The meters at the top show each core, memory and swap; the list below shows the processes, the busiest first. Keys along the bottom sort, search and filter the list.
Examples
htopeverything
htop -u $USERonly your processes
htop -tas a tree: which started which
htop -p 1234,5678only these process IDs
F3 F4 (in htop) search / filter
F5 tree view
F6 sort by a column
F10 quit
Options
-u USER- only USER's processes
-t, --tree- start in tree view
-p PIDS- only these processes
-d N- the update delay, in tenths of a second
-s COLUMN- sort by COLUMN
Notes
- F2 is the setup screen: meters, columns and colours, saved to
~/.config/htop/htoprc. - Memory shown as "used" leaves out the page cache; a nearly full bar of cache is normal.
See also copal-tm, btop, rc-status
lazygit A terminal interface for git: stage, commit, branch, rebase and push from panels.
System · terminal program · lazygit 0.48.0 · stage 7 · Compilers, editors, Claude Code and the ~/code checkouts · home
needs git
On Copal: The catalogue's git interface, and the one Copal's Neovim opens with Space g g, in a window over the editor.
Use
Start it in a repository. Panels on the left show status, files, branches, commits and stashes; the right shows what the selection is. Keys act on the selection, and the foot of the screen lists them.
Examples
lazygitthe repository here
lazygit -p ~/code/copalanother repository
lazygit -f README.mdthe history of one file
Space (in lazygit) stage or unstage the file
c commit the staged changes
P p push / pull
Tab / 1-5 move between panels
? every key here; q quit
Options
-p, --path DIR- the repository to open
-f, --filter PATH- only the history that touches PATH
-c, --config- print the default config
-cd, --print-config-dir- where its config lives
Notes
- Its config is
~/.config/lazygit/config.yml; lazygit -c prints every setting with its default, to copy from. - Whatever it does is ordinary git:
git log and git status in a shell show the same repository.
See also git, gitui, tig, nvim
lbu Save a RAM-resident Alpine system's changes to disk (the apkovl).
System · alpine-conf 3.22.0 · Alpine's base system · man lbu(8) · home
needs openrc
On Copal: Copal's first two stages run from RAM, the way Alpine boots from a card, and anything they change is gone at the next boot unless lbu commits it. Stage 3 moves the system onto the disk; after that, lbu has nothing to do.
lbu SUBCOMMAND [OPTIONS] [ARGS]
Use
On a diskless Alpine system, every file lives in RAM. lbu commit packs the changed configuration -- /etc and the list of installed packages, by default -- into an .apkovl.tar.gz on the boot medium, and the next boot unpacks it. On an installed Copal machine (every machine past stage 3) you will not need it.
Examples
lbu statuswhat changed since the last commit
lbu diffthe same, as a diff
doas lbu commit -dsave, and delete the older archive
doas lbu include /root/notes.txttrack a file outside /etc
lbu include -lwhat has been added to the set
lbu listevery file the next commit will pack
Options
commit, ci- write the apkovl to the medium
-d- with commit: remove the old apkovl first
-n- with commit: dry run, show what would be packed
status, st- changes since the last commit (A added, U updated, D deleted)
diff- the changes as a diff
include, add- add a file or directory to what is saved
exclude, ex- leave one out
list, ls- the files that would be packed
list-backup, lb- the older timestamped archives
revert REV- go back to one of them
Notes
- Only
/etc and apk's world are saved unless you lbu include more. A home directory in RAM is lost at every reboot. - The medium is
LBU_MEDIA in /etc/lbu/lbu.conf -- the boot partition. Copal sets it from the partition it actually booted from (a Pi's mmcblk0p1, a PC's sda1, a VM's vda1). df / says which kind of system this is: a disk partition means installed, and lbu does not apply; tmpfs means diskless, and it does.
See also setup-alpine, apk
logread Read BusyBox syslogd's in-memory log.
System · busybox 1.37.0 · Alpine's base system · man busybox(1) · home
a BusyBox applet: busybox logread --help, and BusyBox's page
On Copal: Alpine's usual answer to "where is the log" -- and on Copal the wrong one: Copal's syslogd writes the file /var/log/messages, not the in-memory buffer logread reads.
Use
On an Alpine system whose syslogd keeps a circular buffer in memory (started with -C), print it, or follow it. On Copal, read the file instead: the same messages, kept across reboots.
Examples
tail -50 /var/log/messagesCopal: the latest system messages
tail -f /var/log/messagesCopal: follow them
grep sshd /var/log/messagesone service's lines
logread -felsewhere: follow the buffer
Options
-f- follow: print new messages as they arrive
-F- the same, after printing the whole buffer first
Notes
- On Copal
logread answers "can't find syslogd buffer": syslogd runs with SYSLOGD_OPTS="-t" (see /etc/conf.d/syslog), which writes the file. That is expected, not a fault. /var/log/messages belongs to the group wheel, so an administrator reads it without doas.- Kernel messages are not in it: read them with
doas dmesg.
See also dmesg, rc-status, busybox
mkinitfs Build the initramfs: the small first root that finds and mounts the real one.
System · mkinitfs 3.14.1 · stage 10 · Wireless, audio, capture and disks · man mkinitfs(1) · home
needs apk-tools, busybox-binsh, kmod, lddtree, mdev-conf, libblkid, cryptsetup-libs, kmod-libs
On Copal: Every kernel install and upgrade runs it, through apk's trigger: setup-disk in stage 3, and each apk upgrade that brings a new kernel. You call it by hand only after changing what it includes.
mkinitfs [OPTIONS] [KERNELVERSION]
Use
Pack the kernel modules and tools needed to reach the root filesystem -- the disk controller, the filesystem, USB -- into /boot/initramfs-*. Which ones is set by features= in /etc/mkinitfs/mkinitfs.conf. Add a feature, then rebuild.
Examples
cat /etc/mkinitfs/mkinitfs.confthe features this machine uses
mkinitfs -Levery feature there is
mkinitfs -l | lessdry run: the files it would pack
doas mkinitfsrebuild for the running kernel
ls /lib/modulesthe kernel versions installed
Options
KERNELVERSION- build for that kernel (a name in /lib/modules); default the running one
-L- list the available features
-l- dry run: list the files it would include
-F FEATURES- use these features instead of the config's
-o FILE- write to FILE instead of /boot
-c FILE- read another config file
-C ALGORITHM- compress with gzip (default), xz, zstd, lz4 or none
Notes
- A root on something the features do not name -- NVMe, LVM, an encrypted disk -- boots to "mounting root failed" and an emergency shell. Add
nvme, lvm or cryptsetup to features= and rebuild before rebooting onto it. - After a kernel upgrade, reboot soon: the running kernel's modules have been replaced, so loading a new module fails until you do.
- "WARNING: no kernel found" during stage 3 is expected: setup-disk runs on the RAM system, which has no kernel package of its own.
See also apk, lsblk
neofetch The original system-summary-with-a-logo script.
System · command-line tool · neofetch 7.1.0 · stage 18 · The Copal Store, and OpenShot compiled · on the Copal Apps shelf · man neofetch(1) · home
needs bash
On Copal: The store keeps it for the recipes and screenshots that name it; fastfetch is its faster successor and the one to use day to day.
neofetch func_name --option "value" --option "value"
Use
Run it; it prints the system's details beside an ASCII logo. It is a bash script, so it is slower than fastfetch, and no longer developed.
Examples
neofetchthe summary
neofetch --offno logo
neofetch --ascii_distro archanother distribution's logo
neofetch --config noneignore any config file
Options
--off- no ASCII art
--ascii_distro NAME- use that distribution's logo
--config FILE- another config file; none for the defaults
--backend NAME- how to show an image (ascii, off...)
Notes
- Upstream stopped in 2020: details of newer hardware and desktops may be missing or wrong. fastfetch reports them correctly.
- It comes from Alpine's testing repository (
neofetch@testing).
See also fastfetch
setup-alpine Alpine's installer: keyboard, hostname, network, time, users, sshd, disk.
System · alpine-conf 3.22.0 · Alpine's base system · man setup-alpine(8) · home
needs openrc
On Copal: Stage 1 runs it with an answer file that copal-prep.sh wrote on the Mac, so the first boot asks almost nothing. Copal gives it no disk (DISKOPTS=none): stage 3 installs to disk itself.
setup-alpine [-ahq] [-c FILE | -f FILE]
Use
Run once on a new Alpine system. It calls a family of smaller scripts in turn -- setup-keymap, setup-interfaces, setup-timezone, setup-user, setup-sshd and the rest -- and those are the useful part afterwards: each one redoes a single step on a machine already running.
Examples
doas setup-interfacesredo the network, wifi included
doas setup-timezonechange the time zone
doas setup-keymapchange the keyboard layout
doas setup-apkreposchoose another package mirror
setup-alpine -c answers.txtwrite a blank answer file, change nothing
cat /media/*/answers.txtthe answers Copal's stage 1 used
Options
-f FILE- install from an answer file (a path or a URL)
-c FILE- write an answer file template and stop
-q- quick: hostname, networking and a mirror, nothing else
-e- set an empty root password (implied by -q)
-a- write an apkovl only; install nothing to disk
Notes
- An answer file is a shell script it sources:
KEYMAPOPTS, HOSTNAMEOPTS, INTERFACESOPTS, USEROPTS, DISKOPTS and so on. There is no variable for the root password; Copal answers that prompt itself. - Run over SSH, it leaves the network running while it rewrites the settings, so the connection you are using is not cut from under you.
- The other setup scripts are in
/usr/sbin: ls /usr/sbin/setup-*. Each has its own man page: man setup-interfaces.
See also lbu, doas, wpa_passphrase
sha224sum Compute or check SHA-224 checksums; its siblings do MD5 and the other SHA sizes.
System · command-line tool · coreutils 9.11 · stage 12 · The application catalogue · man sha224sum(1) · home
needs coreutils-env, coreutils-fmt, coreutils-sha512sum, acl-libs, libattr, libcrypto3, utmps-libs
On Copal: The catalogue's row for GNU coreutils' checksum tools: prove a download or a copied file is exactly what it should be. Copal's own downloads are checked against sha256 sums the same way.
sha224sum [OPTIONS] [FILE]...
Use
Give it files and it prints a checksum for each. Save those lines to a file, and -c later checks the files against it. sha256sum is the one most downloads publish; md5sum, sha1sum and sha512sum work alike.
Examples
sha224sum photo.jpgone checksum
sha256sum alpine.isothe size most downloads publish
sha256sum *.iso > SUMSsave checksums for later
sha256sum -c SUMScheck the files against them
echo 'HASH file.iso' | sha256sum -c # check against a published hash
Options
-c, --check- read checksums from a file and check them
--quiet- with -c: print only failures
--status- with -c: print nothing; the exit code says
-b, --binary- read in binary mode (the same on Linux)
Notes
- The line format is the hash, two spaces, then the file name;
-c needs exactly that. - MD5 and SHA-1 catch accidents, not tampering. For checking a download's authenticity, use SHA-256 or longer.
See also curl, rsync
tig A text-mode browser for git history: the log, each commit's diff, blame.
System · terminal program · tig 2.6.1 · stage 12 · The application catalogue · man tig(1) · home
needs git, libncursesw, pcre2
On Copal: The catalogue's git history reader: faster than scrolling git log -p, and its blame view walks back through a line's past.
tig [options] [revisions] [--] [paths]
tig log [options] [revisions] [--] [paths]
tig show [options] [revisions] [--] [paths]
tig reflog [options] [revisions]
tig blame [options] [rev] [--] path
tig grep [options] [pattern]
tig refs [options]
tig stash [options]
tig status
tig < [Git command output]
Use
With no arguments it lists the commits; Enter opens one's diff in a split below. It takes the same arguments as git log, and has views for blame, status and refs.
Examples
tigthe log
tig README.mdcommits that touched one file
tig blame src/main.cwho changed each line
tig statusstage and unstage, like git add -p
tig --allevery branch
Enter (in tig) open the selection
j k move; q back, or quit
/ search
Options
blame FILE- the blame view
status- the status view
refs- branches and tags
--all- every ref, not just the current branch
PATH- only commits touching PATH
Notes
- In the blame view, a comma on a line moves blame to the commit before it: the way to follow a line back.
- Settings go in
~/.tigrc (or ~/.config/tig/config).
See also git, lazygit, gitui, delta