1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
# sb-builder
Desktop GUI for managing a Slackware SlackBuilds build VM from one place. It
runs slackrepo builds, overlay syncs (sbpull, sbshadow) and hint file updates
on the VM over ssh, as background jobs that keep running when the GUI
disconnects and can be reattached later. Upstream versions are checked with
nvchecker on the desktop. A dashboard shows VM and repository state,
including the packages SBo lists without a maintainer, and the GUI can start
the VM through libvirt when it is off.
It is built around one setup: a Slackware64-current VM building a personal
repository with [slackrepo](https://github.com/aclemons/slackrepo), laid out
by [slackrepo_setup](https://forge.slackware.nl/danix/slackrepo_setup) (the
SBo tree plus overlays as git subtrees). The defaults (VM `buildsystem`,
repository `SBo-danix`, overlays `personal` and `pentesting`) are the
author's; every one of them is a config key. `nvchecker.toml` is the
author's list of tracked packages.
Still to come: a guarded full repository rebuild, and an SBo orphans screen.
The design, one spec per phase, is in `docs/design/`.
## Requirements
- Desktop: Python 3.11 or newer, PyQt6 (with QtDBus), ssh access to the VM,
optionally `virsh` for starting the VM and `nvchecker` for upstream checks
- VM: Python 3.11 or newer, root ssh login, the
[slackrepo_setup](https://forge.slackware.nl/danix/slackrepo_setup) tools (`sbpull`, `sbshadow`,
`slackrepo_setup_SBo-danix.sh`)
## VM setup
1. A Slackware64-current VM with Python 3.11 or newer (stock), reachable over
ssh as root with a key. A host alias in `~/.ssh/config` keeps the GUI config
short. For start and resume from the GUI, a libvirt domain on the desktop.
2. slackrepo and slackrepo-hints (SBo) installed on the VM.
3. The repository and its slackrepo config from
[slackrepo_setup](https://forge.slackware.nl/danix/slackrepo_setup): follow
its Install section, fill `/etc/slackrepo/SBo-danix.local`, then run
`slackrepo_setup_SBo-danix.sh` once to build the repository.
4. Package signing: a gpg key in root's keyring, `/root/.genreprc` with
`USE_GPGAGENT=1` and `REPOSOWNERGPG=<fingerprint>` (read by slackrepo's
`gen_repos_files.sh`), and slackrepo_setup's `gpg-agent.conf`, which lets
the GUI unlock the key for jobs.
5. `./install.sh --remote` from the desktop (below) installs the helper and
`/etc/sb-builder/config.toml`. For another repository, set `repo_dir`,
`overlays`, `slackrepo_repo`, `slackrepo_db`, `hintdir` and
`slackrepo_logdir` there.
6. The phantom deps list (`/etc/sb-builder/phantom-deps`) starts empty; fill it
from Hints, Phantom deps.
## Install
./install.sh # ~/bin/sb-builder and menu entry -> this repo, GUI config if missing
./install.sh --remote # helper to the VM, its config if missing (asks first)
`BINDIR` changes the launcher directory, `SBB_TARGET` the ssh destination for
`--remote` (default `buildsystem`). Configs:
- GUI: `~/.config/sb-builder/config.toml`, see `config.example.toml`
- VM: `/etc/sb-builder/config.toml`, see `remote/config.example.toml`
Every key is optional. Both configs also have settings pages in Keystone (the
quickshell desktop shell); the files stay hand-editable. The GUI rereads its
config when the file changes (`File > Reload config` does it by hand), and
Keystone edits the VM's through `sbb-remote config-get` / `config-set`, which
refuse a file that does not load and keep the previous one as `config.toml.bak`.
Column widths, sort order, splitter positions and the window size are kept
across runs in `~/.config/sb-builder/state.conf` (delete it to reset them; on
Wayland the compositor may still pick the window size).
## Usage
sb-builder
The window has six tabs, always open: Dashboard, Packages, Hints, Results,
Repository, Jobs (Ctrl+PgUp/PgDn cycle them). The ribbon at the top holds the current
tab's actions, in the order a task uses them; the smaller bar under it holds
its view controls (select, clear, refresh). An action that does not apply is
greyed out, its tooltip says why. Actions act on the **ticked** rows: a click
anywhere on a row ticks or unticks it, Ctrl+A ticks every visible row,
Ctrl+Shift+A unticks all.
Starting a job keeps you where you are; the Jobs tab shows "(running)" and
then the end status. When a job you started ends, its next step comes to you
as a dialog: after a preview, its log with **Run it** (and a **publish** box);
after a hint change, the diff with **Revert** and **Build these**. **Not
now** loses nothing: **Run it** in the Jobs tab, on a finished preview,
reopens it.
- **Dashboard**: VM load, uptime and free disk, package counts, slackrepo
build results, last overlay pull, SBo orphans, recent jobs. Refreshes while
visible. The tiles open Packages (the orphans tile with only the orphaned
filter on), Results (one result kind) and Jobs; Built lists the packages
to prune (built, SlackBuild gone).
- **Packages**: every package of the repository, with built version, hint
and status (`ok`, `failed`, `never`, `outdated`, `newer`: built newer than
the target, e.g. after a pin left its hint, so a build would downgrade). The
hint column says what the hint does: `pin` (sets `VERSION`), `deps` (only
`DELREQUIRES`/`ADDREQUIRES`), `skip`, `other`. Search by name or summary,
or with `cat:`, `maint:`, `req:`, `status:`, `hint:` (`hint:none` for no
hint); toggle the overlay and status
chips, and **orphaned** for the packages SBo lists without a maintainer.
The detail pane shows the package's versions, its dependencies after
hints (dropped ones struck through), what its hint file does, and a link
to it in Hints. **Build** (also updates outdated packages), **Rebuild**,
**Remove** and **Update all** run a slackrepo `--preview` first; **Prune**
removes built packages whose SlackBuild is gone from the tree (e.g. moved
to Slackware), the same removal Update all does, without building. A run
whose packages fail is marked failed and opens **Build results**: each
package's result, its log, and **Retry failed**; **New hint** creates hints, pinned
at the `.info` version, for the ticked packages without one; **Publish**
pushes the package repository (untick **publish** at Run it to hold a run
back and publish later).
- **Hints**: every package with a hint or an nvchecker stanza, with hint,
`.info` and upstream version. **Check upstream** runs nvchecker on the
desktop over `nvchecker.toml` in this repo (stanza name = package name,
edit it by hand to track a package; `hints.nvchecker_keyfile` gives it a
GitHub token) and ticks the outdated packages. **Update selected** rewrites
their hints on the VM (version, URLs, md5 of the downloaded source; with
**No download** on, `DOWNLOAD="no"` instead; a hint sbshadow wrote,
`DELREQUIRES` only, gets the `.info` version lines added). **Delete hint**
removes the ticked packages' hints, each kept as a `.bak`, revertable from
the dialog that follows. **Phantom deps…** keeps the list of deps
-current ships, which SBo packages still require (SBo drops a package once
it is official): add names, or tick suggestions, the required names no
package of the tree has; **Apply to hints** writes them into the
`DELREQUIRES` of every package that requires them (sbshadow does the same
after each sync). An update downloads every URL the bump changed for its
md5; a package with bundled deps (helper config `[manifests]`, neovim by
default) first has its extra downloads moved to the versions upstream's
deps list names.
- **Results**: slackrepo's last build attempt per package, newest first,
filterable by result. **Show build log** (or double-click) opens the end of
the log of the package's last attempt (slackrepo keeps one per command:
`build.log`, `update.log`, `rebuild.log`, `remove.log`), where it reports
the failure, with its `resource.log` (load, memory, tmp over the build).
- **Repository**: the packages slackrepo built, read from the local mount of
its package repository (`[repository] path`, default `/repo`; no VM
needed). Tiles for count (per overlay), size, unpublished (opens that
filter) and last publish; search by name or description, overlay and `unpublished` chips;
the detail pane shows the description, sizes and the package's ChangeLog
entries, with a link to it in Packages.
- **Jobs**: every job with its live log. **Pull overlay** (`sbpull <overlay>`)
and **Check shadowing** (`sbshadow`) run as previews; when one finds
`shadow:` or `unshadow:` lines, its dialog offers **Apply shadowing**.
**Rebuild tree** (after a confirm) replaces the SBo-danix tree with a fresh
clone of upstream and the overlays (`slackrepo_setup_SBo-danix.sh`); the live
tree stays until the new one is ready. **Kill** stops the selected running job.
- Real runs sign the repository. When the package signing key is locked
(status bar 🔒), the GUI asks for its passphrase first and hands it to the
VM's gpg-agent; it is never stored.
Jobs run on the VM detached from the ssh session, one at a time. Closing the
GUI or losing the connection does not stop them; reopening the job resumes
the log. Job state and logs live in `/var/lib/sb-builder/jobs/` on the VM.
When ssh fails and `vm.domain` is set, the status bar shows the libvirt state
of the VM and offers to start or resume it. Desktop notifications report
finished, failed, killed and lost jobs, and the VM coming up: the job as title,
how it went (exit code, duration) as body, an icon per outcome.
## License
Copyright (C) 2026 Danilo M. <danix@danix.xyz>
GPLv2 only. See [LICENSE](LICENSE) for the full text.
## Development Approach
This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback.
All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions.
The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability.
|