[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
#!/usr/bin/env bash
# Build a portable EternalTerminal `et` client inside manylinux2014.
#
# Inputs (env):
# ET_REF — git ref of MisterTea/EternalTerminal to build (e.g. et-v6.2.10)
# ARCH — x64 | arm64 (for output naming only; container is already that arch)
# OUT_DIR — directory to write et-linux-<arch>.tar.gz + sha256
#
# Output:
# $OUT_DIR/et-linux-<arch>.tar.gz (single `et` client binary)
# $OUT_DIR/et-linux-<arch>.tar.gz.sha256
#
# Strategy: build inside manylinux2014 (glibc 2.17) for broad distro
# compatibility. EternalTerminal vendors vcpkg under external/vcpkg and uses
# manifest mode, so its third-party deps (protobuf, libsodium, openssl, ...)
# are built as static archives by vcpkg's x64-linux / arm64-linux triplet.
# The resulting `et` still depends on baseline Linux system libraries
# (glibc family), compatible with virtually every distro since 2014.
#
# `et` is a pure network-transport client; it renders no terminal locally and
# needs no terminfo database, so the bundle ships only the binary.
set -euo pipefail
: "${ET_REF:?missing ET_REF}"
: "${ARCH:?missing ARCH}"
: "${OUT_DIR:?missing OUT_DIR}"
validate_et_ref() {
if [[ ! "$ET_REF" =~ ^[A-Za-z0-9][A-Za-z0-9._/-]*$ ]] \
|| [[ "$ET_REF" == *..* ]] \
|| [[ "$ET_REF" == *@\{* ]] \
|| [[ "$ET_REF" == */ ]] \
|| [[ "$ET_REF" == *.lock ]]; then
echo "ERROR: invalid ET_REF: $ET_REF" >&2
exit 1
fi
}
validate_et_ref
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
mkdir -p "$OUT_DIR"
# manylinux2014 ships a devtoolset gcc and git, but an old cmake/ninja.
# Install modern cmake + ninja from PyPI (vcpkg requires cmake >= 3.x).
yum install -y -q zip unzip tar curl perl-IPC-Cmd >/dev/null 2>&1 || true
# manylinux ships CPython interpreters under /opt/python/<tag>/bin but puts
# none of them on PATH (a bare `python3` fails with 127). Prefer a known
# *stable* cpXY: picking "newest" would grab pre-release builds such as
# 3.15.0b1, which we don't want driving the cmake/ninja install.
if ! command -v python3 >/dev/null 2>&1; then
for tag in cp313 cp312 cp311 cp310; do
if [ -x "/opt/python/$tag-$tag/bin/python3" ]; then
export PATH="/opt/python/$tag-$tag/bin:$PATH"
break
fi
done
fi
command -v python3 >/dev/null 2>&1 \
|| { echo "ERROR: no stable python3 under /opt/python (manylinux layout changed?)" >&2; exit 1; }
python3 -m pip install --quiet --upgrade pip
# Pin cmake < 4: ET's pinned vcpkg baseline and some ports don't configure
# cleanly under cmake 4.x. ninja is unconstrained.
python3 -m pip install --quiet "cmake>=3.25,<4" ninja
export PATH="$(python3 -c 'import sysconfig,os;print(os.path.join(sysconfig.get_path("scripts")))'):$PATH"
NINJA_BIN=$(command -v ninja)
retry_command() {
local attempt=1
local max_attempts=4
local delay=15
until "$@"; do
local status=$?
if [ "$attempt" -ge "$max_attempts" ]; then
return "$status"
fi
echo "WARN: command failed with exit $status; retrying in ${delay}s (attempt $((attempt + 1))/$max_attempts): $*" >&2
sleep "$delay"
attempt=$((attempt + 1))
delay=$((delay * 2))
done
}
cd "$WORK"
# Fetch EternalTerminal at the requested ref, with the vendored vcpkg
# submodule. Branch names, tags, and commit SHAs all work.
git init et
git -C et remote add origin https://github.com/MisterTea/EternalTerminal.git
git -C et fetch --depth 1 origin "$ET_REF"
git -C et checkout --detach FETCH_HEAD
git -C et submodule update --init --recursive --depth 1
# Drop sentry-native from the vcpkg manifest. We build with
# -DDISABLE_TELEMETRY=ON, so ET's CMake never calls find_package(sentry) nor
# links it; but vcpkg's manifest mode still force-builds every listed dep
# during configure. sentry-native pulls in crashpad, is the heaviest dep, and
# fails to build on arm64-linux — dropping it fixes arm64 and speeds up all.
if ! grep -q '"sentry-native"' "$WORK/et/vcpkg.json"; then
echo "ERROR: sentry-native not in vcpkg.json (ET manifest changed?)" >&2; exit 1
fi
grep -v '"sentry-native"' "$WORK/et/vcpkg.json" > "$WORK/et/vcpkg.json.tmp"
mv "$WORK/et/vcpkg.json.tmp" "$WORK/et/vcpkg.json"
# Build only the Release halves of the vcpkg deps (skip the Debug pass) to
# roughly halve build time. Overlay triplets mirror ET's chosen community
# triplet but force release-only; selected via VCPKG_OVERLAY_TRIPLETS so the
# vendored vcpkg tree stays untouched.
OVERLAY="$WORK/vcpkg-overlay-triplets"
mkdir -p "$OVERLAY"
for t in x64-linux arm64-linux; do
src=$(find "$WORK/et/external/vcpkg/triplets" -name "$t.cmake" | head -1)
[ -n "$src" ] || { echo "ERROR: vcpkg triplet $t.cmake not found" >&2; exit 1; }
cp "$src" "$OVERLAY/$t.cmake"
echo 'set(VCPKG_BUILD_TYPE release)' >> "$OVERLAY/$t.cmake"
done
export VCPKG_OVERLAY_TRIPLETS="$OVERLAY"
# Bootstrap the vendored vcpkg so CMake's vcpkg toolchain can resolve the
# manifest deps.
( cd et && ./external/vcpkg/bootstrap-vcpkg.sh -disableMetrics )
BUILD_DIR="$WORK/et/build"
# ET's CMake sets its own vcpkg toolchain + triplet (auto-detected from
# uname -m); we supply only the generator + build type. DISABLE_TELEMETRY=ON
# keeps ET from using Sentry, matching the manifest edit above.
#
# CMAKE_CXX_STANDARD_LIBRARIES=-lanl: ET (via cpp-httplib) references glibc's
# async DNS resolver getaddrinfo_a / gai_* (which live in libanl), but ET's
# link line omits -lanl, so linking `et` fails with "undefined reference to
# getaddrinfo_a". STANDARD_LIBRARIES is appended after all other libraries —
# exactly where the linker needs it to resolve those symbols.
retry_command cmake -S "$WORK/et" -B "$BUILD_DIR" \
-GNinja \
-DCMAKE_MAKE_PROGRAM="$NINJA_BIN" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DDISABLE_TELEMETRY=ON \
-DCMAKE_CXX_STANDARD_LIBRARIES=-lanl
cmake --build "$BUILD_DIR" --target et
BUNDLE_DIR="$WORK/linux-$ARCH-bundle"
mkdir -p "$BUNDLE_DIR"
OUT_BIN="$BUNDLE_DIR/et"
cp "$BUILD_DIR/et" "$OUT_BIN"
strip "$OUT_BIN"
echo "--- file ---"
file "$OUT_BIN"
echo "--- ldd ---"
ldd "$OUT_BIN" || true
echo "--- size ---"
ls -lh "$OUT_BIN"
# Sanity check: must not link any non-system shared libraries. Allow only the
# glibc runtime family and the ELF loader (matches the mosh build policy).
ldd "$OUT_BIN" > "$WORK/ldd.txt" || true
awk '
/=>/ { print $1; next }
/^[[:space:]]*\/.*ld-linux/ { print $1; next }
' "$WORK/ldd.txt" > "$WORK/deps.txt"
if grep -Ev '^(linux-vdso\.so\.1|lib(c|m|pthread|rt|dl|resolv|util|z|stdc\+\+|gcc_s|atomic|anl)\.so\.[0-9]+|/lib.*/ld-linux.*\.so\.[0-9]+|ld-linux.*\.so\.[0-9]+)$' "$WORK/deps.txt"; then
echo "ERROR: et links a non-system shared library; static linking failed." >&2
exit 1
fi
BUNDLE_TGZ="$OUT_DIR/et-linux-$ARCH.tar.gz"
( cd "$BUNDLE_DIR" && tar -czf "$BUNDLE_TGZ" "et" )
( cd "$OUT_DIR" && sha256sum "et-linux-$ARCH.tar.gz" > "et-linux-$ARCH.tar.gz.sha256" )
cat "$OUT_DIR/et-linux-$ARCH.tar.gz.sha256"

View File

@@ -0,0 +1,133 @@
#!/usr/bin/env bash
# Build a universal EternalTerminal `et` client on macOS (arm64 + x86_64).
#
# Inputs (env):
# ET_REF — git ref of MisterTea/EternalTerminal to build (e.g. et-v6.2.10)
# OUT_DIR — directory to write et-darwin-universal.tar.gz + sha256
# MACOSX_DEPLOYMENT_TARGET — min macOS (default 11.0)
#
# Output:
# $OUT_DIR/et-darwin-universal.tar.gz (single universal `et`)
# $OUT_DIR/et-darwin-universal.tar.gz.sha256
#
# Builds each arch separately (vcpkg arm64-osx / x64-osx static triplets) and
# lipo-combines the two `et` binaries. Links only macOS system dylibs.
set -euo pipefail
: "${ET_REF:?missing ET_REF}"
: "${OUT_DIR:?missing OUT_DIR}"
export MACOSX_DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET:-11.0}"
validate_et_ref() {
if [[ ! "$ET_REF" =~ ^[A-Za-z0-9][A-Za-z0-9._/-]*$ ]] \
|| [[ "$ET_REF" == *..* ]] \
|| [[ "$ET_REF" == *@\{* ]] \
|| [[ "$ET_REF" == */ ]] \
|| [[ "$ET_REF" == *.lock ]]; then
echo "ERROR: invalid ET_REF: $ET_REF" >&2
exit 1
fi
}
validate_et_ref
command -v ninja >/dev/null 2>&1 || brew install ninja
command -v cmake >/dev/null 2>&1 || brew install cmake
command -v autoconf >/dev/null 2>&1 || brew install automake autoconf libtool
NINJA_BIN=$(command -v ninja)
retry_command() {
local attempt=1
local max_attempts=4
local delay=15
until "$@"; do
local status=$?
if [ "$attempt" -ge "$max_attempts" ]; then
return "$status"
fi
echo "WARN: command failed with exit $status; retrying in ${delay}s (attempt $((attempt + 1))/$max_attempts): $*" >&2
sleep "$delay"
attempt=$((attempt + 1))
delay=$((delay * 2))
done
}
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
mkdir -p "$OUT_DIR"
cd "$WORK"
git init et
git -C et remote add origin https://github.com/MisterTea/EternalTerminal.git
git -C et fetch --depth 1 origin "$ET_REF"
git -C et checkout --detach FETCH_HEAD
git -C et submodule update --init --recursive --depth 1
# Drop sentry-native from the vcpkg manifest — see build-linux.sh for the
# full rationale. -DDISABLE_TELEMETRY=ON means ET never references Sentry,
# yet vcpkg's manifest would otherwise force-build it (and crashpad) anyway.
if ! grep -q '"sentry-native"' "$WORK/et/vcpkg.json"; then
echo "ERROR: sentry-native not in vcpkg.json (ET manifest changed?)" >&2; exit 1
fi
grep -v '"sentry-native"' "$WORK/et/vcpkg.json" > "$WORK/et/vcpkg.json.tmp"
mv "$WORK/et/vcpkg.json.tmp" "$WORK/et/vcpkg.json"
# Release-only vcpkg deps (skip the Debug pass) to halve build time, via
# overlay triplets that mirror the osx triplets but force release-only.
OVERLAY="$WORK/vcpkg-overlay-triplets"
mkdir -p "$OVERLAY"
for t in arm64-osx x64-osx; do
src=$(find "$WORK/et/external/vcpkg/triplets" -name "$t.cmake" | head -1)
[ -n "$src" ] || { echo "ERROR: vcpkg triplet $t.cmake not found" >&2; exit 1; }
cp "$src" "$OVERLAY/$t.cmake"
echo 'set(VCPKG_BUILD_TYPE release)' >> "$OVERLAY/$t.cmake"
done
export VCPKG_OVERLAY_TRIPLETS="$OVERLAY"
( cd et && ./external/vcpkg/bootstrap-vcpkg.sh -disableMetrics )
build_arch() {
local arch="$1" # arm64 | x86_64
local triplet="$2" # arm64-osx | x64-osx
local build_dir="$WORK/build-$arch"
echo "=== building et for $arch ($triplet) ===" >&2
retry_command cmake -S "$WORK/et" -B "$build_dir" \
-GNinja \
-DCMAKE_MAKE_PROGRAM="$NINJA_BIN" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DDISABLE_TELEMETRY=ON \
-DCMAKE_OSX_ARCHITECTURES="$arch" \
-DVCPKG_TARGET_TRIPLET="$triplet"
cmake --build "$build_dir" --target et
echo "$build_dir/et"
}
ARM_BIN=$(build_arch arm64 arm64-osx | tail -1)
X64_BIN=$(build_arch x86_64 x64-osx | tail -1)
BUNDLE_DIR="$WORK/darwin-universal-bundle"
mkdir -p "$BUNDLE_DIR"
OUT_BIN="$BUNDLE_DIR/et"
lipo -create -output "$OUT_BIN" "$ARM_BIN" "$X64_BIN"
strip "$OUT_BIN" || true
echo "--- lipo info ---"
lipo -info "$OUT_BIN"
echo "--- otool -L ---"
otool -L "$OUT_BIN" || true
# Sanity check: only macOS system dylibs (/usr/lib, /System/Library) allowed.
# A universal binary makes `otool -L` print a "<path> (architecture X):"
# header per slice; key off the "(compatibility version ...)" suffix that only
# real dependency lines carry, so those per-arch headers aren't misread as a
# non-system dylib (tail -n +2 only drops the first one).
if otool -L "$OUT_BIN" | awk '/\(compatibility version/ {print $1}' \
| grep -Ev '^(/usr/lib/|/System/Library/)' | grep -q .; then
echo "ERROR: et links a non-system dylib; static linking failed." >&2
otool -L "$OUT_BIN" >&2
exit 1
fi
BUNDLE_TGZ="$OUT_DIR/et-darwin-universal.tar.gz"
( cd "$BUNDLE_DIR" && tar -czf "$BUNDLE_TGZ" "et" )
( cd "$OUT_DIR" && shasum -a 256 "et-darwin-universal.tar.gz" > "et-darwin-universal.tar.gz.sha256" )
cat "$OUT_DIR/et-darwin-universal.tar.gz.sha256"

View File

@@ -0,0 +1,129 @@
# Build a static EternalTerminal `et` client on Windows (x64, MSVC).
#
# Inputs (env):
# ET_REF — git ref of MisterTea/EternalTerminal to build (e.g. et-v6.2.10)
# OUT_DIR — directory to write et-win32-x64.tar.gz + sha256
#
# Output:
# $OUT_DIR/et-win32-x64.tar.gz (single static et.exe, no DLLs)
# $OUT_DIR/et-win32-x64.tar.gz.sha256
#
# Uses the vendored vcpkg x64-windows-static triplet so the produced et.exe
# statically links the MSVC runtime and all third-party deps — no DLL bundle
# is needed. Run from a Developer Command Prompt (ilammy/msvc-dev-cmd) so
# cl.exe / ninja are on PATH.
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
if (-not $env:ET_REF) { throw "missing ET_REF" }
if (-not $env:OUT_DIR) { throw "missing OUT_DIR" }
function Invoke-WithRetry {
param(
[Parameter(Mandatory = $true)]
[scriptblock]$Command,
[int]$MaxAttempts = 4,
[int]$InitialDelaySeconds = 15
)
$attempt = 1
$delay = $InitialDelaySeconds
while ($true) {
& $Command
if ($LASTEXITCODE -eq 0) { return }
if ($attempt -ge $MaxAttempts) {
throw "command failed after $attempt attempts (exit $LASTEXITCODE)"
}
Write-Warning "command failed with exit $LASTEXITCODE; retrying in ${delay}s (attempt $($attempt + 1)/$MaxAttempts)"
Start-Sleep -Seconds $delay
$attempt++
$delay *= 2
}
}
$etRef = $env:ET_REF
if ($etRef -notmatch '^[A-Za-z0-9][A-Za-z0-9._/-]*$' -or $etRef -match '\.\.' -or $etRef -match '@\{' -or $etRef.EndsWith('/') -or $etRef.EndsWith('.lock')) {
throw "invalid ET_REF: $etRef"
}
# Root the build just under the drive root. vcpkg unpacks dependencies into
# <work>\et\external_imported\vcpkg\buildtrees\... and libsodium's bundled
# MSBuild project pulls sources via long "..\..\..\..\src\..." relative paths.
# Rooted in %TEMP% (~60 chars) the unnormalized path exceeds Windows MAX_PATH
# (260) and fails with "C1083: Cannot open source file". A short drive-root
# (e.g. C:\et-XXXXXXXX) keeps every path comfortably under the limit.
$work = "$env:SystemDrive\et-" + [System.Guid]::NewGuid().ToString("N").Substring(0, 8)
if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Force -Path $work | Out-Null
New-Item -ItemType Directory -Force -Path $env:OUT_DIR | Out-Null
try {
$etDir = Join-Path $work "et"
git init $etDir
git -C $etDir remote add origin https://github.com/MisterTea/EternalTerminal.git
git -C $etDir fetch --depth 1 origin $etRef
git -C $etDir checkout --detach FETCH_HEAD
git -C $etDir submodule update --init --recursive --depth 1
# Drop sentry-native from the vcpkg manifest. We configure with
# -DDISABLE_TELEMETRY=ON so ET never references Sentry, but vcpkg's manifest
# mode would still force-build it (and crashpad). Removing it avoids an
# unused heavy dependency and speeds up the build.
$manifest = Join-Path $etDir "vcpkg.json"
if (-not (Select-String -Path $manifest -Pattern '"sentry-native"' -Quiet)) {
throw "sentry-native not in vcpkg.json (ET manifest changed?)"
}
(Get-Content $manifest) | Where-Object { $_ -notmatch '"sentry-native"' } | Set-Content $manifest
# Build only the Release halves of the vcpkg deps (skip Debug) to roughly
# halve build time, via an overlay triplet mirroring x64-windows-static but
# forcing release-only.
$overlay = Join-Path $work "vcpkg-overlay-triplets"
New-Item -ItemType Directory -Force -Path $overlay | Out-Null
$srcTriplet = Join-Path $etDir "external\vcpkg\triplets\x64-windows-static.cmake"
if (-not (Test-Path $srcTriplet)) {
$srcTriplet = Join-Path $etDir "external\vcpkg\triplets\community\x64-windows-static.cmake"
}
if (-not (Test-Path $srcTriplet)) { throw "vcpkg triplet x64-windows-static.cmake not found" }
Copy-Item $srcTriplet (Join-Path $overlay "x64-windows-static.cmake")
Add-Content -Path (Join-Path $overlay "x64-windows-static.cmake") -Value 'set(VCPKG_BUILD_TYPE release)'
$env:VCPKG_OVERLAY_TRIPLETS = $overlay
& (Join-Path $etDir "external\vcpkg\bootstrap-vcpkg.bat") -disableMetrics
$buildDir = Join-Path $etDir "build"
Invoke-WithRetry {
cmake -S $etDir -B $buildDir `
-GNinja `
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
-DDISABLE_TELEMETRY=ON `
-DVCPKG_TARGET_TRIPLET=x64-windows-static
}
cmake --build $buildDir --target et
if ($LASTEXITCODE -ne 0) { throw "cmake build failed" }
$bundleDir = Join-Path $work "win32-x64-bundle"
New-Item -ItemType Directory -Force -Path $bundleDir | Out-Null
$srcExe = Join-Path $buildDir "et.exe"
if (-not (Test-Path $srcExe)) { $srcExe = Join-Path $buildDir "RelWithDebInfo\et.exe" }
Copy-Item $srcExe (Join-Path $bundleDir "et.exe")
# Report any non-system DLL imports (informational; a static build should
# only import the in-box Windows DLLs).
Write-Host "--- et.exe built ---"
Get-Item (Join-Path $bundleDir "et.exe") | Format-List Name, Length
$tgz = Join-Path $env:OUT_DIR "et-win32-x64.tar.gz"
# Windows ships bsdtar as tar.exe.
tar -czf $tgz -C $bundleDir "et.exe"
if ($LASTEXITCODE -ne 0) { throw "tar failed" }
$hash = (Get-FileHash -Algorithm SHA256 $tgz).Hash.ToLower()
$sumLine = "$hash et-win32-x64.tar.gz"
Set-Content -Path (Join-Path $env:OUT_DIR "et-win32-x64.tar.gz.sha256") -Value $sumLine -NoNewline
Write-Host $sumLine
}
finally {
Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue
}