scripts/ensure-tmp-symlink
#!/usr/bin/env bash
ensure-tmp-symlink
#
Sets up the project's two-tier RAM scratch, per the CLAUDE.md convention:
#
tmp/ -> /tmp/neocities-modernization/ (RAM, EXEC allowed)
tmp/shared-memory/ -> /dev/shm/neocities-modernization/ (RAM, noexec)
#
The project's tmp/ points at a per-project dir under /tmp/, which is RAM where
/tmp is a tmpfs and — crucially — allows execution, so compiled binaries and
dlopen'd .so files can live and run there. Nested inside it, tmp/shared-memory/
points at /dev/shm/, which every modern Linux guarantees to be RAM but commonly
mounts noexec: the right home for logs, compiled build artifacts, and other
NON-executable data. Rule of thumb: things you RUN go in tmp/; things you WRITE
(logs, dumps, caches) go in tmp/shared-memory/.
#
Idempotent and self-healing: it creates whatever is missing and repoints a
symlink that aims at the wrong target (a symlink holds no data, so re-aiming it
loses nothing). It refuses loudly only when a real directory or file sits where
a symlink belongs — those bytes might be someone's, and moving them into
volatile RAM would be worse than a loud refusal that asks a human to look.
#
Usage:
scripts/ensure-tmp-symlink # uses hard-coded DIR
scripts/ensure-tmp-symlink /path/to/project/root # overrides DIR
source scripts/ensure-tmp-symlink # bash callers can source
set -eu
{{{ DIR resolution
Hard-coded project root with first-argument override, per the project-wide
convention for scripts.
DIR="${1:-/mnt/mtwo/programming/ai-stuff/neocities-modernization}"
}}}
{{{ TARGET resolution
EXEC_TARGET is the exec-capable RAM tier (under /tmp); SHM_TARGET is the
guaranteed-RAM, noexec tier (under /dev/shm). Names are unique per project so
multiple projects on one host do not collide. The shared-memory symlink lives
INSIDE the exec target, so it is reached from the project as tmp/shared-memory/.
EXEC_TARGET="/tmp/neocities-modernization"
SHM_TARGET="/dev/shm/neocities-modernization"
TMP_LINK="${DIR}/tmp" # -> EXEC_TARGET
SHM_LINK="${EXEC_TARGET}/shared-memory" # -> SHM_TARGET; reached as tmp/shared-memory/
}}}
{{{ ensure_targets_exist()
ensure_targets_exist() {
# Both RAM dirs are cheap and wiped on reboot; create whichever is missing.
[ -d "${EXEC_TARGET}" ] || mkdir -p "${EXEC_TARGET}"
[ -d "${SHM_TARGET}" ] || mkdir -p "${SHM_TARGET}"
}
}}}
{{{ ensure_symlink()
Make ${1} a symlink to ${2}. Shared by both tiers so they obey identical rules:
create when missing, repoint a wrong-target symlink in place, refuse a real
directory/file loudly.
ensure_symlink() {
local link_path="${1}"
local want_target="${2}"
# Case: already a symlink. Repoint only if it aims at the wrong place — a
# symlink holds no data, so removing and recreating it loses nothing. This
# is what self-heals an old target (e.g. a pre-two-tier /dev/shm symlink).
if [ -L "${link_path}" ]; then
if [ "$(readlink "${link_path}")" != "${want_target}" ]; then
echo "ensure-tmp-symlink: repointing ${link_path}: '$(readlink "${link_path}")' -> '${want_target}'" >&2
rm "${link_path}"
ln -s "${want_target}" "${link_path}"
fi
return 0
fi
# Case: a real file/dir sits where the symlink belongs. Refuse loudly rather
# than relocate whatever bytes are there into volatile RAM.
if [ -e "${link_path}" ]; then
echo "ERROR: ${link_path} exists but is not a symbolic link." >&2
echo " Move its contents elsewhere, then remove it, then re-run." >&2
echo " Suggested:" >&2
echo " mv '${link_path}' '${link_path}.preserved'" >&2
echo " scripts/ensure-tmp-symlink" >&2
exit 1
fi
# Case: nothing there yet. Fresh-clone path.
ln -s "${want_target}" "${link_path}"
}
}}}
ensure_targets_exist
ensure_symlink "${TMP_LINK}" "${EXEC_TARGET}"
ensure_symlink "${SHM_LINK}" "${SHM_TARGET}"