Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@profullstack/cli-tools",
"version": "0.63.1",
"version": "0.64.0",
"private": true,
"description": "Local command-line tools, in TypeScript, exposed on PATH.",
"type": "module",
Expand Down
28 changes: 28 additions & 0 deletions root-ubuntu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
# 8. moshcode (curl https://moshcode.sh/install.sh | sh)
# + threatcrush CLI (curl https://threatcrush.com/install.sh | sh); the
# enforcing daemon is a separate opt-in (`threatcrush install-service`)
# + hqsh (curl https://hqterm.sh/install | sh -s -- --server), so
# `hqterm connect` works; skipped when already at the latest release
# 9. a per-user ssh-agent as a systemd user service
# 10. motd from $MOTD_URL
# 11. nginx per-user pages, per-user dev apps, TLS
Expand Down Expand Up @@ -3249,6 +3251,8 @@ _sandbox_tools() {
curl -fsSL https://moshcode.sh/install.sh | sh >/dev/null 2>&1
# threatcrush-disable-next-line sh-remote-script-execution first-party installer, same accepted idiom as mise/moshcode above
curl -fsSL https://threatcrush.com/install.sh | sh >/dev/null 2>&1
# threatcrush-disable-next-line sh-remote-script-execution first-party installer (hqsh, for hqterm connect)
curl -fsSL https://hqterm.sh/install | sh -s -- --server >/dev/null 2>&1
true' >/dev/null 2>&1 \
|| warn "$name: one of the tool installers failed (not fatal)"
return 0
Expand Down Expand Up @@ -5151,6 +5155,29 @@ install_moshcode() { as_user "$1" 'curl -fsSL https://moshcode.sh/install.sh | s
# threatcrush-disable-next-line sh-remote-script-execution first-party installer, same accepted idiom as install_moshcode above
install_threatcrush() { as_user "$1" 'curl -fsSL https://threatcrush.com/install.sh | sh'; }

# hqsh, the server half of hqterm (https://hqterm.sh): `hqterm connect HOST`
# and the desktop app reach a box over plain ssh, which runs `hqsh server
# attach` here. There is no service, port or unit to manage: that command starts
# a per-user daemon on demand that holds the shell across disconnects. The
# client finds the binary on PATH or in ~/.local/bin, where the installer puts
# it, so a per-login install is all a box needs.
#
# Idempotent: the installed `hqsh --version` is compared with the latest
# release tag (read from GitHub's redirect, not the rate-limited API), and a
# current install is left alone. Otherwise the installer swaps the binary in
# atomically, so a running daemon is never half-overwritten.
install_hqsh() {
as_user "$1" '
have="$("$HOME/.local/bin/hqsh" --version 2>/dev/null | awk "{print \$2}")"
want="$(curl -fsSI -o /dev/null -w "%{redirect_url}" https://github.com/profullstack/hqsh/releases/latest 2>/dev/null | sed "s|.*/tag/v||")"
if [ -n "$have" ] && [ "$have" = "$want" ]; then
echo "hqsh $have is current"
exit 0
fi
# threatcrush-disable-next-line sh-remote-script-execution first-party installer, same accepted idiom as install_moshcode
curl -fsSL https://hqterm.sh/install | sh -s -- --server --bin="$HOME/.local/bin"'
}

# Enables the ONE per-box enforcing daemon, as root. Fleet-wide enablement is an
# explicit opt-in (the owner's call, 2026-09-25): the daemon auto-bans, so turning it on
# everywhere is a blast-radius decision, not a default. Safe only on >=0.12.4 (a
Expand Down Expand Up @@ -7218,6 +7245,7 @@ else
# separate step: installing moshcode does not update what it manages
try "moshcode tools ($login)" update_moshcode_tools "$login"
try "threatcrush ($login)" install_threatcrush "$login"
try "hqsh ($login)" install_hqsh "$login"
done < <(printf 'root\n'; all_logins)

# One enforcing daemon per box, once, as root -- not per login. Explicit
Expand Down
43 changes: 43 additions & 0 deletions test/root-ubuntu.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1535,3 +1535,46 @@ describe('quiet_networkd_dispatcher', () => {
expect(run(dir, 'FAKE_ACTIVE=1')).toContain('already off');
});
});

describe('install_hqsh', () => {
// as_user is replaced by a plain bash run under a fake HOME, with a curl that
// answers the "latest release" probe with tag v0.2.0 and otherwise serves an
// installer that only reports how it was invoked.
const setup = (installed?: string) => {
const dir = mkdtempSync(join(tmpdir(), 'root-ubuntu-hqsh-'));
mkdirSync(join(dir, 'fakebin'));
mkdirSync(join(dir, 'home/.local/bin'), { recursive: true });
writeFileSync(
join(dir, 'fakebin/curl'),
'#!/bin/bash\ncase " $* " in *" -w "*) echo https://github.com/profullstack/hqsh/releases/tag/v0.2.0 ;; *) echo \'echo "installer ran: $*"\' ;; esac\n',
{ mode: 0o755 },
);
if (installed) {
writeFileSync(join(dir, 'home/.local/bin/hqsh'), `#!/bin/sh\necho "hqsh ${installed}"\n`, { mode: 0o755 });
}
return dir;
};
const run = (dir: string) =>
shell(
['install_hqsh'],
`as_user() { HOME=${JSON.stringify(join(dir, 'home'))} PATH=${JSON.stringify(join(dir, 'fakebin'))}:$PATH bash -c "$2"; }\ninstall_hqsh alice`,
);

it('leaves a current install alone, so a re-run downloads nothing', () => {
expect(run(setup('0.2.0'))).toBe('hqsh 0.2.0 is current');
});

it('runs the server-only installer into ~/.local/bin when hqsh is outdated', () => {
const dir = setup('0.1.0');
expect(run(dir)).toBe(`installer ran: --server --bin=${join(dir, 'home/.local/bin')}`);
});

it('installs hqsh where there is none yet', () => {
expect(run(setup())).toContain('installer ran: --server');
});

it('runs for every login in the tool loop, and inside tenant instances', () => {
expect(SOURCE).toMatch(/try "hqsh \(\$login\)"\s+install_hqsh "\$login"/);
expect(SOURCE).toContain('curl -fsSL https://hqterm.sh/install | sh -s -- --server >/dev/null 2>&1');
});
});
Loading