A first-install run of red-dev 1.0.5 on an Ubuntu 24.04 corporate workstation did not reach the end. boot.sh refused to install twice, the converge finished 7 items failed — this machine is not converged yet (exit 1), the process later died on an uncaught exception, and the terminal it configured came back unreadable.
One report because it's one run, and several findings are the same run's cascade — happy to have it sliced. Every claim below is quoted from the converge log, which is attached in full as a comment.
Environment
|
|
| red-dev |
1.0.5 (~/.local/bin/red-dev, 97 MB) |
| OS |
Ubuntu 24.04.4 LTS, kernel 6.17.0-19-generic, x86_64 |
| Locale |
pt_BR — apt output is localized, which matters for finding 3 |
| Shell/term |
bash + ble.sh, inside zellij, TERM=xterm-256color, alacritty config present |
| Network |
corporate proxy that intercepts TLS (unknown CA in the chain) |
| Endpoint agents |
CrowdStrike falcon-sensor, CyberArk cyberark-epm — see finding 3 |
| Pre-existing |
omakub-style dotfiles, gh authenticated, an earlier red-dev run from 2026-07-15 |
| Log |
~/.local/state/red-dev/2026-08-13T19-40-45-777-menu.log, 740 lines, 8m47s, exit 1 |
1. boot.sh hard-fails on the anonymous GitHub API rate limit, on a machine that had a token available
$ sh ./install.sh
:: resolving stable release of reddb-io/red-dev
fail GitHub API rate limit reached — set GITHUB_TOKEN and retry
# exit 1
$ curl -fsSL https://raw.githubusercontent.com/reddb-io/red-dev/main/boot.sh | sh
:: resolving stable release of reddb-io/red-dev
fail GitHub API rate limit reached — set GITHUB_TOKEN and retry
# exit 1
The message is accurate and the hint is the right hint — but the very first thing a new machine does is spend one of 60 anonymous calls/hour, and behind a shared corporate NAT that budget is somebody else's. gh was logged in on this box the entire time. It only worked on the third try.
Two cheap fixes, either one avoids this:
- Skip the API on the
stable channel. https://github.com/$REPO/releases/latest/download/$ASSET is a redirect served by github.com, not api.github.com: no quota, no JSON, no tr/awk pipeline. The comment in boot.sh says the API call exists so the version isn't guessed — this doesn't guess a version either. next genuinely needs the API.
- Try a token the machine already has before giving up:
${GITHUB_TOKEN:-$(gh auth token 2>/dev/null)}.
Worth noting the same quota bit the run from the inside: OpenCode's vendor installer ended on Installing opencode version: 1.18.18 / Failed to fetch version information, which is what its GitHub API call looks like when rate-limited.
2. Nothing in the run knows what to do with a TLS-intercepting proxy — that's 3 of the 7 failures
Three separate items, three separate error messages, one cause. None of the three surfaced it in the final panel.
Gemini CLI (log line 79):
npm error code SELF_SIGNED_CERT_IN_CHAIN
npm error request to https://registry.npmjs.org/@google%2fgemini-cli failed,
reason: self-signed certificate in certificate chain
fail Gemini CLI: ~/.local/share/mise/installs/node/26/bin/npm exited non-zero
OpenClaw — its vendor script installs via npm, fails, retries, fails, and red-dev reports installer exited 1. Same npm, same proxy.
Hermes Agent — different tool, same wall:
→ Python 3.11 not found, installing via uv...
error: Failed to install cpython-3.11.15-linux-x86_64-gnu
Caused by: Failed to download https://github.com/astral-sh/.../cpython-3.11.15...tar.gz
Caused by: invalid peer certificate: UnknownIssuer
✗ Failed to install Python 3.11
And a fourth, non-fatal: warn tldr cache download failed; run 'tldr --update' yourself.
The user-visible output for all of this is npm exited non-zero and installer exited 1: <url>, which sends you reading vendor scripts instead of fixing your CA bundle. Two things worth doing:
- Detect it once, in preflight. One probe of
https://github.com that comes back with an unknown issuer tells you the whole story, and it's the difference between four mystery failures and one line: "this network intercepts TLS; red-dev found your corporate CA at /usr/local/share/ca-certificates/… and will point child installers at it."
- Then actually export it to every child:
SSL_CERT_FILE, CURL_CA_BUNDLE, NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, npm's cafile. uv, npm and curl each need to be told separately and none of them read the others' variable.
- Recognise the strings
SELF_SIGNED_CERT_IN_CHAIN, UnknownIssuer, unable to get local issuer certificate in provider output and translate them, rather than passing exited non-zero through.
Separately: mise resolved node@lts to 24.19.0 in this same run, yet the failing npm is .../mise/installs/node/**26**/bin/npm, and OpenClaw's own probe agrees (Active Node.js: v26.5.0). Worth checking which node the agent providers actually run under.
3. One half-configured dpkg poisons the rest of the run — that's the other 4 failures, and only 1 of them is real
builtin:ssh-server is item 8 of 50. It failed, and its summary line is truncated to the first line of apt's output, which carries no information at all:
info ssh-server gave up after 14.4s
[ 8/50] ssh-server builtin:ssh-server failed 14439ms
openssh-server: Lendo listas de pacotes...
gave up after 14.4s reads like a red-dev-side timeout ending apt between unpack and configure. The package is still in that state now:
$ dpkg -l | grep -v '^ii'
iU openssh-server 1:9.6p1-3ubuntu13.18 amd64 secure shell (SSH) server
it desktop-file-utils / gnome-menus / hicolor-icon-theme (triggers pending)
From that point every apt operation in the run fails, because apt won't work around a half-configured package. Three more items died on it, each reporting its own unrelated-looking error:
[19/50] carapace failed → sudo exited 100: sudo -E apt-get install -y .../carapace-bin_1.7.3_linux_amd64.deb
[45/50] wl-clipboard failed → apt-get install failed (100)
[47/50] red-ui failed → sudo exited 100: sudo -E apt-get install -y .../red-ui_0.3.2_amd64.deb
all three with the same real cause a few lines up in the body:
1 pacotes não totalmente instalados ou removidos.
needrestart is being skipped since dpkg has failed
E: Sub-process /usr/bin/dpkg returned an error code (1)
wl-clipboard is the clearest tell: apt said wl-clipboard is already the newest version (2.2.1-1build1), there was nothing to do, and the item failed anyway with 0ms.
And while we're in apt — needrestart is running unrestrained as root inside this transaction:
Restarting services...
/etc/needrestart/restart.d/cyberark-epm.service
systemctl restart falcon-sensor.service
Job for falcon-sensor.service failed because the control process exited with error code.
Service restarts being deferred:
systemctl restart bluetooth.service
/etc/needrestart/restart.d/dbus.service
systemctl restart gdm.service
systemctl restart systemd-logind.service
An installer restarted this machine's EDR agent (and broke it — falcon-sensor.service failed) and had gdm.service and systemd-logind.service queued behind it. Restarting those two would have killed the desktop session mid-install, taking the installer with it. On a corporate-managed machine, bouncing the security agents is also the kind of thing that shows up on somebody's dashboard.
Suggested behaviour for the whole apt path:
DEBIAN_FRONTEND=noninteractive and NEEDRESTART_MODE=l (list, don't act) on every apt invocation. sudo -E faithfully preserving an unset variable doesn't help.
- Don't kill apt on a timeout mid-transaction; if you must, run
sudo dpkg --configure -a before declaring the item failed.
- Check for the half-configured state before each apt item and either repair it once, or fail the remaining apt items as blocked by ssh-server — rather than emitting four independent errors for one cause.
- Keep the last meaningful lines of provider output in the summary, not the first.
Lendo listas de pacotes... as an entire error text is a locale-dependent no-op, and E: Sub-process /usr/bin/dpkg returned an error code (1) was three lines away.
4. builtin:alacritty deletes a file that the user's own alacritty.toml still imports
Confirmed, straight from the log — this one is self-inflicted:
:: builtin: alacritty
info writing the Alacritty config, then theming every surface that takes one
removed theme.toml — the ANSI colours are yours again
skip alacritty.toml exists — cursor, font and keys updated, yours left alone
ok themed: vscode, wallpaper, gnome, redwall
It removed theme.toml and, in the same breath, left alacritty.toml alone because it was the user's. But that file's first line is:
import = [ "~/.config/alacritty/theme.toml", "~/.config/alacritty/font.toml", "~/.config/alacritty/font-size.toml", "~/.config/alacritty/shared.toml" ]
So the config now imports a path that red-dev deleted, and every alacritty launch starts by failing to load its config. red-dev.json meanwhile records "theme": "obsidian". If the provider is going to remove a file, it has to remove the import that points at it — or leave the file alone. "Yours, left alone" and "I deleted part of it" can't both be true.
5. The font it installed and configured is incomplete, and named differently on every surface
This is what actually stopped work — after the run, every terminal renders in a wrong-metrics face: thin strokes, cells far wider than the glyphs in them, so a full-width TUI wraps and reads as broken. (Screenshot to follow in the thread.) red-dev.json says "font": "firacode", "setupCompleted": true. Nothing else hangs together:
- Two faces out of a 26.8 MB download. The log states it plainly:
:: nerd font: FiraCode -> FiraCode Nerd Font Mono … ok FiraCode Nerd Font Mono installed (2 faces). On disk that's exactly FiraCodeNerdFontMono-Regular.ttf and -Bold.ttf. No italic, no bold-italic.
- …while the config it wrote asks for the face it didn't install.
~/.config/alacritty/font.toml contains [font.italic] family = 'FiraCode Nerd Font Mono', style = 'Italic'. No such face exists, so every italic/dim run of text — which a TUI like Claude Code emits constantly — falls back to a different font with different metrics.
- A different family on the GNOME side.
org.gnome.desktop.interface monospace-font-name was set to 'FiraMono Nerd Font 10' — FiraMono, not FiraCode. Both families happen to exist here, so it fails quietly instead of loudly:
$ fc-list : family | tr ',' '\n' | grep -i fira | sort -u
FiraCode Nerd Font Mono ← the 2 faces red-dev installed
FiraMono Nerd Font (+ Mono / Propo / Medium variants) ← what red-dev pointed GNOME at
The GNOME Terminal profile was left at 'Monospace 12', untouched.
- And it was pointed there before the font existed.
ok themed: … gnome … is item 33 of 50; builtin:nerd-font that downloads and installs the family is item 49. Even if the names had matched, the theming step ran 16 items before the font it names was on disk.
- Its own font size is silently discarded.
alacritty.toml imports font.toml then font-size.toml. red-dev's font.toml sets size = 11; font-size.toml — whose own comment reads "Leave this file in place for omakub to rely on a shared font size for all terminal apps" — sets size = 10 and wins by coming later. Writing a fragment into someone else's import chain without reading what follows it will keep producing this.
- Leftovers from the previous run. The 2026-07-15 run dropped ~100
CaskaydiaMonoNerdFont*.ttf files directly into ~/.local/share/fonts/; 1.0.5 installs into ~/.local/share/fonts/red-dev/FiraCode/ instead. The old family is still installed and still a fallback candidate. Whatever the new layout is, it should adopt or clean up the old one.
Concretely: install the whole family (or stop referencing styles you didn't install), use one family name across alacritty/GNOME/VS Code, install the font before pointing anything at it.
6. A duplicate agents pass runs twice, concurrently, after the 50-item converge — and its failure is what makes the run exit 1
The 50 items finish at [50/50] wsl-sync … skipped. Then the mise-and-agents sequence starts over — twice, with interleaved output, two /tmp paths one millisecond apart:
[50/50] wsl-sync skip (no distro to reach into from a Linux desktop)
:: mise: node@lts
...
:: mise: node@lts ← a second pass, interleaved with the first
...
info saving to /tmp/red-dev-installer-1786651426823.sh ← OpenCode, again
info saving to /tmp/red-dev-installer-1786651427191.sh ← OpenCode, again, concurrently
info received 13.4 KB of shell
info received 13.4 KB of shell
info running it with bash
info running it with bash
Installing opencode version: 1.18.18
Failed to fetch version information
fail OpenCode: installer exited 1: https://opencode.ai/install
OpenCode had already installed successfully in the first pass (ok OpenCode, log line 78). This second/third execution re-downloaded the vendor script, re-ran it, hit the GitHub API limit from finding 1, and failed. Two problems, then: the whole batch re-runs concurrently instead of nothing re-running at all, and a duplicate re-run of an item that already succeeded contributes to the failure state.
The accounting also disagrees with itself: fail OpenCode: installer exited 1 is in the log, the panel says 7 items failed and lists seven without OpenCode, and the totals line reads 64 items · 25 changed · 31 already present · 7 failed — 25 + 31 + 7 = 63, not 64.
7. Uncaught PromptCancelledError — red-dev crashes instead of exiting when a prompt is cancelled
~/.local/state/red-dev/crash.log:
=== 2026-08-13T20:05:36.005Z uncaughtException red-dev 1.0.5 linux ===
PromptCancelledError: Prompt cancelled
at handleKeypress (/$bunfs/root/red-dev-linux-x64:25346:16)
at emit (node:events:95:22)
at addChunk (internal:streams/readable:264:47)
at readableAddChunkPushByteMode (internal:streams/readable:242:18)
at internalRead (native:38:40)
at processTicksAndRejections (native:7:39)
Timestamp lines up with the wallpaper step (2026-08-13T20-05-34-656-wallpaper.log). Cancelling a prompt is ordinary input, not an exception to leak to the top level: it should unwind to a clean exit, restore the terminal, and not write a crash report.
8. Smaller things from the same log
red-ui's release has a checksums file that doesn't cover its own asset: info published checksums: checksums.txt → warn checksums.txt has no entry for red-ui_0.3.2_amd64.deb → info no published checksum; recording sha256 …. That one's your own release, fixable at the source.
- Every vendor installer runs unverified:
info no published checksum; recording sha256 … before info running it with bash, for 114 KB (OpenClaw) and 145 KB (Hermes) of third-party shell as root-adjacent. The record-on-first-sight behaviour is a reasonable design, but it's worth being explicit that first contact is unverified by construction.
.bashrc was backed up and rewritten (:: backed up this .bashrc to .bashrc.red-dev-backup) in the same run that later crashed — fine here, worth knowing it happens before the run is known to succeed.
What the end looked like
┌──────────────────────────────────────────────────────────────────────┐
│ ✗ 7 items failed — this machine is not converged yet │
│ │
│ 64 items · 25 changed · 31 already present · 7 failed │
│ took 8m 47s │
└──────────────────────────────────────────────────────────────────────┘
# exit 1
The panel's advice — → Re-run red-dev install — every provider is idempotent, it resumes here. — can't work for findings 3, 4 and 5: the apt items keep failing until dpkg --configure -a is run by hand, the deleted theme.toml stays deleted, and re-running rewrites the same font config and re-points GNOME at the same absent family.
A first-install run of
red-dev1.0.5 on an Ubuntu 24.04 corporate workstation did not reach the end.boot.shrefused to install twice, the converge finished7 items failed — this machine is not converged yet(exit 1), the process later died on an uncaught exception, and the terminal it configured came back unreadable.One report because it's one run, and several findings are the same run's cascade — happy to have it sliced. Every claim below is quoted from the converge log, which is attached in full as a comment.
Environment
~/.local/bin/red-dev, 97 MB)TERM=xterm-256color, alacritty config presentfalcon-sensor, CyberArkcyberark-epm— see finding 3ghauthenticated, an earlier red-dev run from 2026-07-15~/.local/state/red-dev/2026-08-13T19-40-45-777-menu.log, 740 lines, 8m47s, exit 11.
boot.shhard-fails on the anonymous GitHub API rate limit, on a machine that had a token availableThe message is accurate and the hint is the right hint — but the very first thing a new machine does is spend one of 60 anonymous calls/hour, and behind a shared corporate NAT that budget is somebody else's.
ghwas logged in on this box the entire time. It only worked on the third try.Two cheap fixes, either one avoids this:
stablechannel.https://github.com/$REPO/releases/latest/download/$ASSETis a redirect served by github.com, notapi.github.com: no quota, no JSON, notr/awkpipeline. The comment inboot.shsays the API call exists so the version isn't guessed — this doesn't guess a version either.nextgenuinely needs the API.${GITHUB_TOKEN:-$(gh auth token 2>/dev/null)}.Worth noting the same quota bit the run from the inside: OpenCode's vendor installer ended on
Installing opencode version: 1.18.18 / Failed to fetch version information, which is what its GitHub API call looks like when rate-limited.2. Nothing in the run knows what to do with a TLS-intercepting proxy — that's 3 of the 7 failures
Three separate items, three separate error messages, one cause. None of the three surfaced it in the final panel.
Gemini CLI (log line 79):
OpenClaw — its vendor script installs via npm, fails, retries, fails, and red-dev reports
installer exited 1. Same npm, same proxy.Hermes Agent — different tool, same wall:
And a fourth, non-fatal:
warn tldr cache download failed; run 'tldr --update' yourself.The user-visible output for all of this is
npm exited non-zeroandinstaller exited 1: <url>, which sends you reading vendor scripts instead of fixing your CA bundle. Two things worth doing:https://github.comthat comes back with an unknown issuer tells you the whole story, and it's the difference between four mystery failures and one line: "this network intercepts TLS; red-dev found your corporate CA at/usr/local/share/ca-certificates/…and will point child installers at it."SSL_CERT_FILE,CURL_CA_BUNDLE,NODE_EXTRA_CA_CERTS,REQUESTS_CA_BUNDLE, npm'scafile.uv,npmandcurleach need to be told separately and none of them read the others' variable.SELF_SIGNED_CERT_IN_CHAIN,UnknownIssuer,unable to get local issuer certificatein provider output and translate them, rather than passingexited non-zerothrough.Separately:
miseresolvednode@ltsto 24.19.0 in this same run, yet the failing npm is.../mise/installs/node/**26**/bin/npm, and OpenClaw's own probe agrees (Active Node.js: v26.5.0). Worth checking which node the agent providers actually run under.3. One half-configured
dpkgpoisons the rest of the run — that's the other 4 failures, and only 1 of them is realbuiltin:ssh-serveris item 8 of 50. It failed, and its summary line is truncated to the first line of apt's output, which carries no information at all:gave up after 14.4sreads like a red-dev-side timeout ending apt between unpack and configure. The package is still in that state now:From that point every apt operation in the run fails, because apt won't work around a half-configured package. Three more items died on it, each reporting its own unrelated-looking error:
all three with the same real cause a few lines up in the body:
wl-clipboardis the clearest tell: apt saidwl-clipboard is already the newest version (2.2.1-1build1), there was nothing to do, and the item failed anyway with0ms.And while we're in apt —
needrestartis running unrestrained as root inside this transaction:An installer restarted this machine's EDR agent (and broke it —
falcon-sensor.service failed) and hadgdm.serviceandsystemd-logind.servicequeued behind it. Restarting those two would have killed the desktop session mid-install, taking the installer with it. On a corporate-managed machine, bouncing the security agents is also the kind of thing that shows up on somebody's dashboard.Suggested behaviour for the whole apt path:
DEBIAN_FRONTEND=noninteractiveandNEEDRESTART_MODE=l(list, don't act) on every apt invocation.sudo -Efaithfully preserving an unset variable doesn't help.sudo dpkg --configure -abefore declaring the item failed.Lendo listas de pacotes...as an entire error text is a locale-dependent no-op, andE: Sub-process /usr/bin/dpkg returned an error code (1)was three lines away.4.
builtin:alacrittydeletes a file that the user's ownalacritty.tomlstill importsConfirmed, straight from the log — this one is self-inflicted:
It removed
theme.tomland, in the same breath, leftalacritty.tomlalone because it was the user's. But that file's first line is:So the config now imports a path that red-dev deleted, and every alacritty launch starts by failing to load its config.
red-dev.jsonmeanwhile records"theme": "obsidian". If the provider is going to remove a file, it has to remove the import that points at it — or leave the file alone. "Yours, left alone" and "I deleted part of it" can't both be true.5. The font it installed and configured is incomplete, and named differently on every surface
This is what actually stopped work — after the run, every terminal renders in a wrong-metrics face: thin strokes, cells far wider than the glyphs in them, so a full-width TUI wraps and reads as broken. (Screenshot to follow in the thread.)
red-dev.jsonsays"font": "firacode","setupCompleted": true. Nothing else hangs together::: nerd font: FiraCode -> FiraCode Nerd Font Mono…ok FiraCode Nerd Font Mono installed (2 faces). On disk that's exactlyFiraCodeNerdFontMono-Regular.ttfand-Bold.ttf. No italic, no bold-italic.~/.config/alacritty/font.tomlcontains[font.italic] family = 'FiraCode Nerd Font Mono',style = 'Italic'. No such face exists, so every italic/dim run of text — which a TUI like Claude Code emits constantly — falls back to a different font with different metrics.org.gnome.desktop.interface monospace-font-namewas set to'FiraMono Nerd Font 10'— FiraMono, not FiraCode. Both families happen to exist here, so it fails quietly instead of loudly:'Monospace 12', untouched.ok themed: … gnome …is item 33 of 50;builtin:nerd-fontthat downloads and installs the family is item 49. Even if the names had matched, the theming step ran 16 items before the font it names was on disk.alacritty.tomlimportsfont.tomlthenfont-size.toml. red-dev'sfont.tomlsetssize = 11;font-size.toml— whose own comment reads "Leave this file in place for omakub to rely on a shared font size for all terminal apps" — setssize = 10and wins by coming later. Writing a fragment into someone else's import chain without reading what follows it will keep producing this.CaskaydiaMonoNerdFont*.ttffiles directly into~/.local/share/fonts/; 1.0.5 installs into~/.local/share/fonts/red-dev/FiraCode/instead. The old family is still installed and still a fallback candidate. Whatever the new layout is, it should adopt or clean up the old one.Concretely: install the whole family (or stop referencing styles you didn't install), use one family name across alacritty/GNOME/VS Code, install the font before pointing anything at it.
6. A duplicate agents pass runs twice, concurrently, after the 50-item converge — and its failure is what makes the run exit 1
The 50 items finish at
[50/50] wsl-sync … skipped. Then the mise-and-agents sequence starts over — twice, with interleaved output, two/tmppaths one millisecond apart:OpenCode had already installed successfully in the first pass (
ok OpenCode, log line 78). This second/third execution re-downloaded the vendor script, re-ran it, hit the GitHub API limit from finding 1, and failed. Two problems, then: the whole batch re-runs concurrently instead of nothing re-running at all, and a duplicate re-run of an item that already succeeded contributes to the failure state.The accounting also disagrees with itself:
fail OpenCode: installer exited 1is in the log, the panel says7 items failedand lists seven without OpenCode, and the totals line reads64 items · 25 changed · 31 already present · 7 failed— 25 + 31 + 7 = 63, not 64.7. Uncaught
PromptCancelledError— red-dev crashes instead of exiting when a prompt is cancelled~/.local/state/red-dev/crash.log:Timestamp lines up with the wallpaper step (
2026-08-13T20-05-34-656-wallpaper.log). Cancelling a prompt is ordinary input, not an exception to leak to the top level: it should unwind to a clean exit, restore the terminal, and not write a crash report.8. Smaller things from the same log
red-ui's release has a checksums file that doesn't cover its own asset:info published checksums: checksums.txt→warn checksums.txt has no entry for red-ui_0.3.2_amd64.deb→info no published checksum; recording sha256 …. That one's your own release, fixable at the source.info no published checksum; recording sha256 …beforeinfo running it with bash, for 114 KB (OpenClaw) and 145 KB (Hermes) of third-party shell as root-adjacent. The record-on-first-sight behaviour is a reasonable design, but it's worth being explicit that first contact is unverified by construction..bashrcwas backed up and rewritten (:: backed up this .bashrc to .bashrc.red-dev-backup) in the same run that later crashed — fine here, worth knowing it happens before the run is known to succeed.What the end looked like
The panel's advice —
→ Re-run red-dev install — every provider is idempotent, it resumes here.— can't work for findings 3, 4 and 5: the apt items keep failing untildpkg --configure -ais run by hand, the deletedtheme.tomlstays deleted, and re-running rewrites the same font config and re-points GNOME at the same absent family.