installer source / review before running
Read every line before it runs.
This page renders the exact shell script served at /install.sh. Nothing runs here. Review it, inspect the release checksums, then decide whether to install.
What this review proves.
published releaseWaitDojo v0.2.4 archives for macOS, Linux, and WSL2release details →
archive integritySHA-256 detects a corrupt or mismatched downloaded archivechecksums →
trust boundaryEd25519-signed archives and release provenance; v0.2.4 bootstraps verification for later self-updatessecurity details →
The public-proof manifest documents the deterministic UI capture generated from published v0.2.4 and records its archive, binary, and tag identity. It is UI evidence; publisher authenticity comes from the detached signatures and signed release provenance.
Published installer source.
The source below is inert text. Use the explicitly labeled raw-file action only if you want to download it.
#!/bin/sh
set -eu
# Installer output and checksum/archive tools must behave the same on GNU and
# BSD userlands, even when the calling terminal exports a locale unavailable on
# the target host (for example C.UTF-8 on macOS).
LC_ALL=C
LANG=C
export LC_ALL LANG
PRODUCT="waitdojo"
BASE_URL="${WAITDOJO_BASE_URL:-https://waitdojo.nishxnt-97.chatgpt.site/releases}"
VERSION="${WAITDOJO_VERSION:-latest}"
DEFAULT_INSTALL_DIR="$HOME/.local/bin"
INSTALL_DIR="${WAITDOJO_INSTALL_DIR:-$DEFAULT_INSTALL_DIR}"
DRY_RUN="${WAITDOJO_DRY_RUN:-0}"
NO_MODIFY_PATH="${WAITDOJO_NO_MODIFY_PATH:-0}"
AGENT="${WAITDOJO_AGENT:-}"
PATH_PROFILE_CONFIGURED=0
usage() {
cat <<'EOF'
Usage: install.sh [--dry-run] [--no-modify-path] [--agent codex|claude|none]
Environment:
WAITDOJO_INSTALL_DIR install directory, defaults to ~/.local/bin
WAITDOJO_VERSION release version, defaults to latest
WAITDOJO_BASE_URL release base URL, defaults to the live WaitDojo site
WAITDOJO_DRY_RUN set to 1 to print actions without changing files
WAITDOJO_NO_MODIFY_PATH
set to 1 to leave shell profiles unchanged
WAITDOJO_AGENT optionally configure codex or claude hooks after install
EOF
}
while [ "$#" -gt 0 ]; do
case "$1" in
--dry-run)
DRY_RUN=1
;;
--no-modify-path)
NO_MODIFY_PATH=1
;;
--agent)
shift
if [ "$#" -eq 0 ]; then
echo "--agent requires codex, claude, or none" >&2
exit 2
fi
AGENT="$1"
;;
-h|--help)
usage
exit 0
;;
*)
echo "unknown argument: $1" >&2
usage >&2
exit 2
;;
esac
shift
done
case "$AGENT" in
""|none) AGENT="" ;;
codex|claude) ;;
*)
echo "WAITDOJO_AGENT/--agent must be codex, claude, or none" >&2
exit 2
;;
esac
case "$NO_MODIFY_PATH" in
0|1) ;;
*)
echo "WAITDOJO_NO_MODIFY_PATH must be 0 or 1" >&2
exit 2
;;
esac
case "$INSTALL_DIR" in
/*) ;;
*) INSTALL_DIR="$PWD/$INSTALL_DIR" ;;
esac
detect_os() {
os="${WAITDOJO_TEST_UNAME_S:-$(uname -s 2>/dev/null || true)}"
case "$os" in
Darwin) echo "macos" ;;
Linux) echo "linux" ;;
MINGW*|MSYS*|CYGWIN*)
echo "native Windows is not supported; install and run WaitDojo inside WSL2" >&2
exit 1
;;
*)
echo "unsupported OS: $os" >&2
exit 1
;;
esac
}
detect_arch() {
arch="${WAITDOJO_TEST_UNAME_M:-$(uname -m 2>/dev/null || true)}"
case "$arch" in
x86_64|amd64) echo "x64" ;;
arm64|aarch64) echo "arm64" ;;
*)
echo "unsupported architecture: $arch" >&2
exit 1
;;
esac
}
need_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "missing required command: $1" >&2
exit 1
fi
}
is_wsl2() {
if [ "${WAITDOJO_TEST_WSL:-}" = "1" ]; then
return 0
fi
if [ -n "${WSL_INTEROP:-}" ] || [ -n "${WSL_DISTRO_NAME:-}" ]; then
return 0
fi
if [ -r /proc/sys/kernel/osrelease ] && grep -qi "microsoft\\|wsl" /proc/sys/kernel/osrelease; then
return 0
fi
return 1
}
append_posix_path_block() {
profile="$1"
marker="# >>> waitdojo PATH >>>"
if grep -F "$marker" "$profile" >/dev/null 2>&1; then
echo "PATH already configured in $profile"
PATH_PROFILE_CONFIGURED=1
return 0
fi
if {
if [ -s "$profile" ]; then
printf '\n'
fi
printf '%s\n' \
"$marker" \
'# Added by the WaitDojo installer. Remove this block to opt out.' \
'case "$PATH" in' \
' "$HOME/.local/bin"|"$HOME/.local/bin":*) ;;' \
' *) export PATH="$HOME/.local/bin:$PATH" ;;' \
'esac' \
'# <<< waitdojo PATH <<<'
} >>"$profile"
then
echo "configured PATH in $profile"
PATH_PROFILE_CONFIGURED=1
else
echo "warning: could not update PATH in $profile" >&2
fi
}
append_fish_path_block() {
profile="$1"
marker="# >>> waitdojo PATH >>>"
profile_dir="${profile%/*}"
if ! mkdir -p "$profile_dir"; then
echo "warning: could not create $profile_dir for PATH setup" >&2
return 0
fi
if grep -F "$marker" "$profile" >/dev/null 2>&1; then
echo "PATH already configured in $profile"
PATH_PROFILE_CONFIGURED=1
return 0
fi
if {
if [ -s "$profile" ]; then
printf '\n'
fi
printf '%s\n' \
"$marker" \
'# Added by the WaitDojo installer. Remove this block to opt out.' \
'if not contains -- "$HOME/.local/bin" "$PATH[1]"' \
' set -gx PATH "$HOME/.local/bin" $PATH' \
'end' \
'# <<< waitdojo PATH <<<'
} >>"$profile"
then
echo "configured PATH in $profile"
PATH_PROFILE_CONFIGURED=1
else
echo "warning: could not update PATH in $profile" >&2
fi
}
configure_shell_path() {
if [ "$NO_MODIFY_PATH" = "1" ]; then
echo "PATH setup skipped (--no-modify-path)"
return 0
fi
if [ "$INSTALL_DIR" != "$DEFAULT_INSTALL_DIR" ]; then
echo "PATH setup skipped for custom install directory $INSTALL_DIR"
return 0
fi
shell_path="${SHELL:-}"
shell_name="${shell_path##*/}"
case "$shell_name" in
bash)
append_posix_path_block "$HOME/.bashrc"
if [ -f "$HOME/.bash_profile" ]; then
append_posix_path_block "$HOME/.bash_profile"
elif [ -f "$HOME/.bash_login" ]; then
append_posix_path_block "$HOME/.bash_login"
else
append_posix_path_block "$HOME/.profile"
fi
;;
zsh)
append_posix_path_block "${ZDOTDIR:-$HOME}/.zshrc"
;;
fish)
append_fish_path_block "${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/waitdojo.fish"
;;
""|sh|dash|ash|ksh)
append_posix_path_block "$HOME/.profile"
;;
*)
echo "warning: shell $shell_name is not supported for automatic PATH setup" >&2
;;
esac
}
current_waitdojo_path() {
command -v "$PRODUCT" 2>/dev/null || true
}
warn_if_shadowed() {
installed="$INSTALL_DIR/$PRODUCT"
resolved="$(current_waitdojo_path)"
if [ -z "$resolved" ] || [ "$resolved" = "$installed" ]; then
return 0
fi
echo "warning: another waitdojo currently wins on PATH: $resolved" >&2
if [ -x "$resolved" ]; then
shadow_version="$("$resolved" --version 2>/dev/null || true)"
if [ -n "$shadow_version" ]; then
echo " existing: $shadow_version" >&2
fi
fi
echo " installed: $installed" >&2
echo " prepend the installed directory now or open a new terminal after PATH setup" >&2
}
print_next_steps() {
if [ "$RUNTIME" = "wsl2" ]; then
echo " workspace: keep source checkouts under WSL, for example ~/waitdojo, not /mnt/c/..."
fi
resolved="$(current_waitdojo_path)"
if [ "$resolved" != "$INSTALL_DIR/$PRODUCT" ]; then
if [ "$INSTALL_DIR" = "$DEFAULT_INSTALL_DIR" ]; then
shell_install_dir='$HOME/.local/bin'
else
shell_install_dir="$INSTALL_DIR"
fi
echo " current shell: export PATH=\"${shell_install_dir}:\$PATH\""
echo " hash -r 2>/dev/null || true"
if [ "$PATH_PROFILE_CONFIGURED" = "1" ]; then
echo " future shells: PATH is configured; open a new terminal"
elif [ "$NO_MODIFY_PATH" = "1" ]; then
echo " future shells: add the install directory to PATH yourself"
elif [ "$DRY_RUN" = "1" ] && [ "$INSTALL_DIR" = "$DEFAULT_INSTALL_DIR" ]; then
echo " future shells: the installer will configure PATH automatically"
else
echo " future shells: add export PATH=\"${shell_install_dir}:\$PATH\" to your shell profile"
fi
fi
if [ -n "$AGENT" ]; then
if [ "$DRY_RUN" = "1" ]; then
echo " setup: would run $PRODUCT setup --agent $AGENT"
else
echo " setup: $PRODUCT setup --agent $AGENT ran; rerun it any time"
fi
echo " review: open $AGENT and run /hooks"
echo " launch: $INSTALL_DIR/$PRODUCT"
else
echo " start: $PRODUCT"
echo " detects your configured agent and opens the project sidecar"
echo " setup: $PRODUCT setup # or: $PRODUCT setup --agent claude"
echo " launch: $PRODUCT codex # or: $PRODUCT claude"
fi
echo " local: $PRODUCT pane"
echo " toggle: Ctrl+G or click [↑ open WaitDojo] / [↓ collapse]"
echo " advanced: tmux prefix, then C-g, then an action key"
echo " check: $PRODUCT doctor --product"
echo " tools:"
for cmd in cargo tmux codex claude; do
if command -v "$cmd" >/dev/null 2>&1; then
echo " $cmd: ok"
else
echo " $cmd: missing"
fi
done
}
OS="$(detect_os)"
ARCH="$(detect_arch)"
RUNTIME="$OS"
if [ "$OS" = "linux" ] && is_wsl2; then
RUNTIME="wsl2"
fi
ASSET="${PRODUCT}-${OS}-${ARCH}.tar.gz"
URL="${BASE_URL}/${VERSION}/${ASSET}"
echo "WaitDojo installer"
echo " runtime: ${RUNTIME}"
echo " platform: ${OS}-${ARCH}"
echo " asset: ${ASSET}"
echo " install: ${INSTALL_DIR}/${PRODUCT}"
echo " source: ${URL}"
if [ "$DRY_RUN" = "1" ]; then
echo "dry run: no files changed"
echo "next steps:"
print_next_steps
exit 0
fi
need_cmd curl
need_cmd tar
need_cmd install
need_cmd mktemp
need_cmd awk
need_cmd grep
if command -v sha256sum >/dev/null 2>&1; then
CHECKSUM_COMMAND="sha256sum"
elif command -v shasum >/dev/null 2>&1; then
CHECKSUM_COMMAND="shasum"
else
echo "missing required command: sha256sum or shasum" >&2
exit 1
fi
mkdir -p "$INSTALL_DIR"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT INT TERM
curl -fsSL "$URL" -o "$tmp_dir/$ASSET"
if [ "$VERSION" = "latest" ]; then
version_url="${BASE_URL}/${VERSION}/VERSION"
curl -fsSL "$version_url" -o "$tmp_dir/VERSION"
expected_version="$(
awk '
NF {
lines += 1
value = $0
sub(/\r$/, "", value)
}
END {
if (lines != 1 || value == "" || value ~ /[[:space:]]/) exit 1
print value
}
' "$tmp_dir/VERSION"
)" || {
echo "invalid published VERSION from $version_url" >&2
exit 1
}
else
expected_version="$VERSION"
fi
case "$expected_version" in
""|*[!0-9A-Za-z.+-]*)
echo "invalid requested or published WaitDojo version: $expected_version" >&2
exit 1
;;
esac
checksum_url="${URL}.sha256"
curl -fsSL "$checksum_url" -o "$tmp_dir/$ASSET.sha256"
expected_checksum="$(
awk -v asset="$ASSET" '
NF {
lines += 1
name = $2
sub(/^\*/, "", name)
sub(/\r$/, "", name)
hash = tolower($1)
sub(/\r$/, "", hash)
if (lines != 1 || NF != 2 || name != asset || length(hash) != 64 || hash !~ /^[0-9a-f]+$/) {
invalid = 1
}
expected = hash
}
END {
if (lines != 1 || invalid) exit 1
print expected
}
' "$tmp_dir/$ASSET.sha256"
)" || {
echo "invalid checksum file from $checksum_url" >&2
exit 1
}
if [ "$CHECKSUM_COMMAND" = "sha256sum" ]; then
actual_checksum="$(sha256sum "$tmp_dir/$ASSET")"
else
actual_checksum="$(shasum -a 256 "$tmp_dir/$ASSET")"
fi
actual_checksum="${actual_checksum%% *}"
if [ "$actual_checksum" != "$expected_checksum" ]; then
echo "checksum verification failed for $ASSET" >&2
exit 1
fi
echo "$ASSET: checksum verified"
tar -xzf "$tmp_dir/$ASSET" -C "$tmp_dir"
if [ ! -f "$tmp_dir/$PRODUCT" ] || [ ! -x "$tmp_dir/$PRODUCT" ]; then
echo "archive did not contain $PRODUCT binary" >&2
exit 1
fi
version_output="$("$tmp_dir/$PRODUCT" --version)"
printf '%s\n' "$version_output" >"$tmp_dir/version.txt"
if [ "$version_output" != "$PRODUCT $expected_version" ]; then
echo "downloaded WaitDojo version mismatch: expected $PRODUCT $expected_version, got $version_output" >&2
exit 1
fi
"$tmp_dir/$PRODUCT" --help >"$tmp_dir/help.txt"
if ! grep -Eq '(^|[[:space:]])codex([[:space:]]|$)' "$tmp_dir/help.txt" || \
! grep -Eq '(^|[[:space:]])claude([[:space:]]|$)' "$tmp_dir/help.txt"; then
echo "downloaded WaitDojo build is missing Codex or Claude Code support" >&2
exit 1
fi
validation_home="$tmp_dir/validation-home"
mkdir -p "$validation_home"
HOME="$validation_home" \
CODEX_HOME="$validation_home/.codex" \
WAITDOJO_DATA_DIR="$validation_home/.codex/waitdojo" \
"$tmp_dir/$PRODUCT" init codex --dry-run --allow-dev-path >/dev/null
HOME="$validation_home" \
CLAUDE_CONFIG_DIR="$validation_home/.claude" \
WAITDOJO_DATA_DIR="$validation_home/.codex/waitdojo" \
"$tmp_dir/$PRODUCT" init claude --dry-run --allow-dev-path >/dev/null
echo "$PRODUCT: Codex and Claude Code support verified"
install -m 0755 "$tmp_dir/$PRODUCT" "$INSTALL_DIR/$PRODUCT"
"$INSTALL_DIR/$PRODUCT" --version >/dev/null
# Bake the install-time campaign bucket (WAITDOJO_CAMPAIGN_BUCKET, if set)
# into the installation identity now; without this, installs that skip
# --agent lose attribution because the env var is gone by first launch.
"$INSTALL_DIR/$PRODUCT" install-stamp >/dev/null 2>&1 || true
echo "installed $PRODUCT to $INSTALL_DIR/$PRODUCT"
configure_shell_path
warn_if_shadowed
if [ -n "$AGENT" ]; then
echo "configuring $AGENT hooks and local teachback via waitdojo setup"
"$INSTALL_DIR/$PRODUCT" setup --agent "$AGENT" || {
echo "waitdojo setup reported remaining gates; the checklist above says what is left" >&2
}
fi
echo "next steps:"
print_next_steps