This document is for people hacking on DXSBash itself. For user-facing docs see README.md, the command reference in commands.md, and the official website at https://dxsbash.digitalxs.ca.
- Repository: https://github.com/digitalxs/dxsbash
- License: GPL-3.0
- Reference platform: Debian 13 (Trixie); also supported: Ubuntu 20.04+, Arch Linux, Fedora 40+
DXSBash is a set of plain shell scripts and rc files — no compiled code, no runtime daemon. Everything revolves around one repo directory that is cloned to a fixed location and then symlinked into place:
~/linuxtoolbox/dxsbash (the cloned repo)
│
┌───────────────┼──────────────────────────────┐
│ rc symlinks │ command symlinks │ config symlinks
▼ ▼ ▼
~/.bashrc /usr/local/bin/dxsbash ~/.config/starship.toml
~/.zshrc /usr/local/bin/update-dxsbash → starship-themes/<theme>.toml
~/.config/ /usr/local/bin/dxsbash-config ~/.config/fastfetch/config.jsonc
fish/ /usr/local/bin/dxsbash-gui
config.fish …repair …doctor …audit …uninstall
desktop integration (desktops only, per user — written by dxsbash-gui --install-desktop):
~/.local/share/applications/dxsbash-settings.desktop (System category)
~/.local/share/icons/hicolor/{16..256,scalable}/apps/dxsbash.{png,svg}
~/.config/systemd/user/dxsbash-update-check.{timer,service} (daily update-notify.sh)
~/.local/share/konsole/DXSBash*.colorscheme (theme-matched colors)
Because every installed file is a symlink back into the repo, a
git pull (via updater.sh) updates the live configuration instantly,
and repair.sh only ever needs to re-create links — user data is never
inside the repo. The one symlink that is user state is
~/.config/starship.toml: it points at whichever theme the user picked
(or is a hand-written file), so updater.sh and repair.sh only relink
it when it is missing or dangling — never back to the default.
Per-user state lives outside the repo in ~/.dxsbash/:
| File | Purpose |
|---|---|
user.conf |
preference overrides sourced by bash/zsh (user.fish for fish) — written only through settings-lib.sh |
custom-aliases.sh |
user aliases from the GUI editor, sourced by bash/zsh after the DXSBash defaults |
custom-aliases.fish |
generated fish twin of custom-aliases.sh (never edit by hand) |
themes/ |
the user's own Starship themes (*.toml), shown in both pickers as id user/<file> |
update-notified |
last version the update notifier announced (one notification per version) |
env-allow |
SHA-256 allowlist for trusted .dxsbash-env files |
logs/ |
installer/updater logs; gui.log holds zenity diagnostics for the last GUI session |
security-summary.txt |
cached login security summary (regenerated) |
suid-baseline.txt |
baseline for dxsbash audit SUID diffing |
| Path | Role |
|---|---|
setup.sh |
interactive + non-interactive installer (menu: install/repair/uninstall) |
updater.sh |
dxsbash update / update-dxsbash — pull latest release |
repair.sh |
re-create symlinks/commands without touching user data |
uninstall.sh |
full removal, restores /etc/skel defaults |
doctor.sh |
read-only health check (pass/warn/fail) |
secaudit.sh |
read-only system security audit (dxsbash audit) |
secsummary.sh |
cached one-line security summary at login (opt-in) |
dxsbash.sh |
umbrella command — dispatches subcommands to the scripts above |
settings-lib.sh |
the settings model — defaults, theme registry, read/write of user.conf/user.fish, theme linking, custom-alias store. Sourced by both settings front ends; add new settings here only |
dxsbash-config.sh |
terminal settings menu (front end over settings-lib.sh) |
dxsbash-gui.sh |
zenity settings window (front end over settings-lib.sh); also owns the menu entry (--install-desktop / --remove-desktop, called by setup/repair/updater) and --selftest |
gui-askpass.sh |
graphical SUDO_ASKPASS helper so sudo can prompt without a terminal |
update-notify.sh |
daily update check → desktop notification with Update now (run by the systemd user timer) |
systemd/ |
dxsbash-update-check.{service,timer} (per-user; installed with the menu entry) |
assets/konsole/ |
Konsole color schemes matched to the built-in themes (see konsole_scheme_for_theme) |
desktop/dxsbash-settings.desktop.in |
menu entry template (@GUI@ is replaced at install time) |
assets/icons/hicolor/ |
app icon: SVG master + pre-rendered PNG sizes (GTK4 only resolves themed icons from sized PNG dirs) |
assets/theme-previews/, assets/screenshots/ |
README images (theme previews are generated — see below) |
tools/ansi2pango.awk |
ANSI → Pango markup converter (POSIX awk); powers the GUI's live theme previews |
tools/render-theme-previews.sh |
dev-only: regenerates assets/theme-previews/*.png |
dxsbash-utils.sh |
shared helpers sourced by .bashrc and .zshrc (logging, cheat, .dxsbash-env trust, ssh-lite selector) |
export-import.sh |
dxsbash export / import — settings backup tarballs |
bench.sh |
dxsbash bench — shell startup benchmarking |
.bashrc, .bash_aliases |
bash configuration (symlinked to ~) |
.zshrc |
zsh configuration |
config.fish |
fish configuration |
.bashrc_help, .zshrc_help, fish_help |
help command content per shell |
commands.md |
command reference (also the data source for cheat) |
starship.toml, starship-themes/ |
prompt presets; ssh-lite.toml is auto-selected over SSH |
config.jsonc |
fastfetch configuration |
reset-*-profile.sh |
revert a user's rc files to distro defaults |
check_dependencies.sh, test_compatibility.sh |
diagnostics |
packaging/build-deb.sh |
builds dist/dxsbash_<version>_all.deb |
packaging/build-arch.sh, packaging/arch/ |
builds the Arch package (PKGBUILD, install hook) |
packaging/dxsbash-installer |
per-user bootstrap shipped by both packages |
.github/workflows/bashtest.yml |
CI: lint, 5-distro install matrix, deb build |
version.txt |
single source of truth for the version |
install.sh |
curl-pipe bootstrap (clones repo, runs setup.sh) |
- Environment check — sudo/root detection (
SUDO_CMD), writable repo dir, sudo/wheel group membership. detectDistro()— parses/etc/os-releaseID, falling back toID_LIKEfor derivatives, and setsDISTROto one ofdebian | arch | fedora | unknown.installDepend()— one branch per family:- debian:
nalawhen usable, elseapt; filters package availability withapt-cache show - arch:
pacman -Sy, availability filter viapacman -Si, then a singlepacman -Su --needed --noconfirmtransaction (avoids partial upgrades) - fedora: availability filter via
dnf info, thendnf install -y
- debian:
- Tool installers — starship, fzf, zoxide via upstream curl
scripts (distro-agnostic); FiraCode Nerd Font unless
DXSBASH_SKIP_FONT=1. - Shell selection — bash/zsh/fish (flag
--shell, envDXSBASH_SHELL, or interactive prompt); zsh gets Oh My Zsh + plugins, fish gets Fisher + Tide. - Linking — rc files into
$HOME, commands into/usr/local/bin, Konsole/Yakuake profiles when KDE is present. - Desktop integration —
detect_desktopinsettings-lib.sh(shared with the updater) reportskde,xfce,otheror nothing. KDE Plasma and XFCE count when installed (plasmashell/xfce4-session, or their session files), so SSH/TTY installs still get the GUI; other desktops need a running session or an installed session file.DXSBASH_DESKTOP=1|0overrides. A desktop addszenityto the dependency list and installs the DXSBash Settings menu entry and update timer; headless servers get neither (no GTK stack).
dxsbash-config.sh (terminal) dxsbash-gui.sh (zenity)
│ │
└──────────► settings-lib.sh ◄───┘
defaults · theme registry · load/write · alias store
│
┌─────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
~/.dxsbash/user.conf ~/.config/starship.toml ~/.dxsbash/custom-aliases.sh
~/.dxsbash/user.fish (symlink → theme) ~/.dxsbash/custom-aliases.fish
│ │ │
└────── sourced by .bashrc / .zshrc / config.fish at startup ──────┘
Rules of the model:
write_settingsalways regenerates the wholeuser.confand its fish twin from theCUR_*values — both front ends, same keys. A new setting = aDEF_*default +load_settings+write_settingsentry.- Values are written in bash's language (
HISTSIZE=-1= unlimited);.zshrctranslates what zsh spells differently (SAVEHIST, no -1). - Themes have ids: a built-in preset's file name, or
user/<file>for~/.dxsbash/themes. Always go throughtheme_entries/theme_path/link_starship_theme— never build paths by hand. apply_terminal_colorsedits onlyColorScheme=in the DXSBash Konsole profile (_ini_set), and only for built-in themes;setup.shcalls it (viadxsbash-gui --apply-colors) right after writing the profile.- Custom aliases are stored as
alias name='cmd'lines; POSIX single-quote escaping ('\'') differs from fish (\'), so the fish file is regenerated from the POSIX one after every change and on every GUI start (hand edits of the.shfile are picked up). - The GUI's theme picker renders each theme's real prompt
(
starship promptinside the user's DXSBash checkout) throughtools/ansi2pango.awkinto Pango markup — no images, the user's own fonts. zenity gotchas handled indxsbash-gui.sh: option text needs a UTF-8 locale (ensure_utf8_locale),--textis backslash-unescaped and markup-parsed (esc),--icontakes an icon name, and in bash ≥ 5.2&in a${var//pat/rep}replacement must be quoted.
Every user-facing feature must work in bash, zsh and fish. The
three rc files deliberately mirror each other section by section
(distribution detection → aliases → special functions → init). Code
that is POSIX-portable between bash and zsh should live once in
dxsbash-utils.sh (sourced by both rc files — cheat, the
.dxsbash-env machinery and the ssh-lite prompt selector live there);
fish always needs its own implementation in config.fish using fish
idioms. Don't shell out to bash from zsh/fish for prompt-path code.
Features that read user state must use ~/.dxsbash/ so they survive
updates.
The .dxsbash-env per-directory files are the one deliberate
exception: they are POSIX sh, sourced natively by bash/zsh, while fish
applies only the portable export KEY=VALUE / alias name='cmd'
subset via a translator (__dxs_env_apply in config.fish).
When touching anything package-related, update all of:
setup.sh—installDepend()family branches.bashrcsetup_package_aliases()+install_bashrc_support().zshrcpackage alias block +install_zshrc_support()config.fishpackage alias block +install_fish_supportrepair.sh/check_dependencies.shinstall hints
Package-name differences to remember: Debian's bat package installs
a batcat binary; nala exists only on Debian/Ubuntu; AUR helpers
(paru/yay) must never run under sudo.
Local quick pass (what CI's lint job runs):
bash dxsbash-gui.sh --selftest # settings model, aliases in bash+fish, menu entry
shellcheck -S warning ./*.sh
bash -n setup.sh .bashrc .bash_aliases
zsh -n .zshrc
fish -n config.fish
./test_compatibility.sh # distro-aware; strict only on Debian 13
bash bench.sh --runs 3 # startup regression checkCI (.github/workflows/bashtest.yml) runs three jobs on every push/PR:
- lint — shellcheck + syntax for all three shells +
dxsbash-gui --selftest - install-test — full
./setup.sh --install --yes --shell bashinsidedebian:13,debian:12,ubuntu:24.04,archlinux:latestandfedora:latestcontainers (withDXSBASH_SKIP_FONT=1), followed bydoctor.sh, config-load, audit and summary smoke tests - build-deb — builds the
.deb, verifies contents, smoke-installs - build-arch — builds the Arch package in
archlinux:latest, installs it
./packaging/build-deb.sh # → dist/dxsbash_<version>_all.deb (needs dpkg-deb)
./packaging/build-arch.sh # → dist/dxsbash-<version>-1-any.pkg.tar.zst (Arch, non-root, makepkg)Both packages ship the repository to /usr/share/dxsbash and install
packaging/dxsbash-installer (shared by both) as /usr/bin/dxsbash-installer.
That per-user bootstrap clones the repo into ~/linuxtoolbox/dxsbash (full
clone, so release fast-forwards work; the packaged tree is the offline
fallback) and runs setup.sh. Packages are distribution vehicles —
nothing in $HOME is owned by the package manager, and multi-user
machines work.
packaging/arch/PKGBUILDbuilds from the GitHub release tarball (v$pkgver), suitable for the AUR.build-arch.shrewrites itspkgver/source/sha256sumsto package the local working tree.build-deb.shalso runs on Arch/Fedora with thedpkgpackage installed (to publish a .deb from there).- CI builds and installs both (
build-deb,build-archjobs) and uploads them as thedxsbash-deb/dxsbash-archartifacts. - Both were verified end to end:
pacman -U+dxsbash-installeron a real Arch root;apt install+dxsbash-installeron Debian/Ubuntu.
updater.sh resolves a channel (--channel flag > user.conf >
$DXSBASH_UPDATE_CHANNEL > stable):
- stable — the newest
vX.Y.Ztag fromgit ls-remote(pre-release tags like-betaare skipped); the localmainbranch is fast-forwarded to it (never moved backwards). - main —
git pull origin main, as before.
The decision is commit-based (update_status / commit_update_available):
an update exists when the channel's target commit — the newest tag,
peeled, or main's tip — is not already contained in the checkout. So
no downgrades (a main snapshot ahead of the newest tag is up to date),
unbumped commits on main are seen, and a tag whose version.txt was not
bumped cannot loop. Shallow clones fall back to comparing versions and
are unshallowed on the first stable update. Fresh installs (setup.sh,
install.sh) clone main; stable users then move on at the next tag.
A release therefore reaches stable users only once it is tagged.
- Update
version.txt(semver — this file is the single source of truth). - Add a dated section to
CHANGELOG.md(Keep-a-Changelog format). - Update the version string in
README.md(line 2) and theversion-tagspan inindex.html. - Document new commands in
commands.md, the three help files and, if user-visible, README. - If a theme in
starship-themes/changed, regenerate the README previews:sudo tools/render-theme-previews.sh(needs starship, ImageMagick with Pango, a Nerd Font). - Run the local test pass above; push and let the CI matrix go green.
- Merge to
main, then tag the merge commit — stable-channel users (the default) only receive tagged releases:git tag -a v3.9.0 -m "DXSBash 3.9.0" && git push origin v3.9.0(the tag must matchversion.txt).update-dxsbashthen moves stable machines to the new tag; main-channel machines already followmain.
- Bash scripts:
set -euo pipefailfor new standalone scripts (rc files must NOTset -e— they run inside user shells). - shellcheck-clean at
-S warningfor scripts,-S errorfor rc files; annotate intentional violations with# shellcheck disable=plus a reason. - Keep the
RC/GREEN/YELLOW/CYANcolor convention and the▶ / ✓ / ⚠ / ✗message prefixes used across scripts. - Guard every alias or feature that depends on optional infrastructure
(
command -v/type -qchecks) — a missing tool must never break shell startup. - Comments explain why (constraints, distro quirks), not what.